]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/gc: move componentgen into portable code
authorRuss Cox <rsc@golang.org>
Wed, 18 Mar 2015 16:29:40 +0000 (12:29 -0400)
committerRuss Cox <rsc@golang.org>
Fri, 20 Mar 2015 04:56:54 +0000 (04:56 +0000)
Change-Id: I652cc7a33a186d1041f62f6e7581421496832a27
Reviewed-on: https://go-review.googlesource.com/7747
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
17 files changed:
src/cmd/5g/cgen.go
src/cmd/5g/galign.go
src/cmd/5g/ggen.go
src/cmd/6g/cgen.go
src/cmd/6g/galign.go
src/cmd/6g/ggen.go
src/cmd/7g/cgen.go
src/cmd/7g/galign.go
src/cmd/7g/ggen.go
src/cmd/8g/cgen.go
src/cmd/8g/galign.go
src/cmd/8g/ggen.go
src/cmd/9g/cgen.go
src/cmd/9g/galign.go
src/cmd/9g/ggen.go
src/cmd/internal/gc/gen.go
src/cmd/internal/gc/go.go

index a6cc54db6ff832800a023c0472a45a7417121309..fae1699a0494ed1fb909c205df68bbb3b224dc20 100644 (file)
@@ -1530,7 +1530,7 @@ func sgen(n *gc.Node, res *gc.Node, w int64) {
        }
 
        // Avoid taking the address for simple enough types.
-       if componentgen(n, res) {
+       if gc.Componentgen(n, res) {
                return
        }
 
@@ -1725,268 +1725,3 @@ func sgen(n *gc.Node, res *gc.Node, w int64) {
        regfree(&src)
        regfree(&tmp)
 }
-
-func cadable(n *gc.Node) bool {
-       if n.Addable == 0 {
-               // dont know how it happens,
-               // but it does
-               return false
-       }
-
-       switch n.Op {
-       case gc.ONAME:
-               return true
-       }
-
-       return false
-}
-
-/*
- * copy a composite value by moving its individual components.
- * Slices, strings and interfaces are supported.
- * Small structs or arrays with elements of basic type are
- * also supported.
- * nr is N when assigning a zero value.
- * return 1 if can do, 0 if cant.
- */
-func componentgen(nr *gc.Node, nl *gc.Node) bool {
-       var nodl gc.Node
-       var nodr gc.Node
-
-       freel := 0
-       freer := 0
-
-       switch nl.Type.Etype {
-       default:
-               goto no
-
-       case gc.TARRAY:
-               t := nl.Type
-
-               // Slices are ok.
-               if gc.Isslice(t) {
-                       break
-               }
-
-               // Small arrays are ok.
-               if t.Bound > 0 && t.Bound <= 3 && !gc.Isfat(t.Type) {
-                       break
-               }
-
-               goto no
-
-               // Small structs with non-fat types are ok.
-       // Zero-sized structs are treated separately elsewhere.
-       case gc.TSTRUCT:
-               fldcount := int64(0)
-
-               for t := nl.Type.Type; t != nil; t = t.Down {
-                       if gc.Isfat(t.Type) {
-                               goto no
-                       }
-                       if t.Etype != gc.TFIELD {
-                               gc.Fatal("componentgen: not a TFIELD: %v", gc.Tconv(t, obj.FmtLong))
-                       }
-                       fldcount++
-               }
-
-               if fldcount == 0 || fldcount > 4 {
-                       goto no
-               }
-
-       case gc.TSTRING,
-               gc.TINTER:
-               break
-       }
-
-       nodl = *nl
-       if !cadable(nl) {
-               if nr != nil && !cadable(nr) {
-                       goto no
-               }
-               igen(nl, &nodl, nil)
-               freel = 1
-       }
-
-       if nr != nil {
-               nodr = *nr
-               if !cadable(nr) {
-                       igen(nr, &nodr, nil)
-                       freer = 1
-               }
-       } else {
-               // When zeroing, prepare a register containing zero.
-               var tmp gc.Node
-               gc.Nodconst(&tmp, nl.Type, 0)
-
-               regalloc(&nodr, gc.Types[gc.TUINT], nil)
-               gmove(&tmp, &nodr)
-               freer = 1
-       }
-
-       // nl and nr are 'cadable' which basically means they are names (variables) now.
-       // If they are the same variable, don't generate any code, because the
-       // VARDEF we generate will mark the old value as dead incorrectly.
-       // (And also the assignments are useless.)
-       if nr != nil && nl.Op == gc.ONAME && nr.Op == gc.ONAME && nl == nr {
-               goto yes
-       }
-
-       switch nl.Type.Etype {
-       // componentgen for arrays.
-       case gc.TARRAY:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               t := nl.Type
-               if !gc.Isslice(t) {
-                       nodl.Type = t.Type
-                       nodr.Type = nodl.Type
-                       for fldcount := int64(0); fldcount < t.Bound; fldcount++ {
-                               if nr == nil {
-                                       gc.Clearslim(&nodl)
-                               } else {
-                                       gmove(&nodr, &nodl)
-                               }
-                               nodl.Xoffset += t.Type.Width
-                               nodr.Xoffset += t.Type.Width
-                       }
-
-                       goto yes
-               }
-
-               // componentgen for slices.
-               nodl.Xoffset += int64(gc.Array_array)
-
-               nodl.Type = gc.Ptrto(nl.Type.Type)
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-               nodl.Type = gc.Types[gc.Simtype[gc.TUINT]]
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_cap) - int64(gc.Array_nel)
-               nodl.Type = gc.Types[gc.Simtype[gc.TUINT]]
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_cap) - int64(gc.Array_nel)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               goto yes
-
-       case gc.TSTRING:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               nodl.Xoffset += int64(gc.Array_array)
-               nodl.Type = gc.Ptrto(gc.Types[gc.TUINT8])
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-               nodl.Type = gc.Types[gc.Simtype[gc.TUINT]]
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               goto yes
-
-       case gc.TINTER:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               nodl.Xoffset += int64(gc.Array_array)
-               nodl.Type = gc.Ptrto(gc.Types[gc.TUINT8])
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-               nodl.Type = gc.Ptrto(gc.Types[gc.TUINT8])
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               goto yes
-
-       case gc.TSTRUCT:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               loffset := nodl.Xoffset
-               roffset := nodr.Xoffset
-
-               // funarg structs may not begin at offset zero.
-               if nl.Type.Etype == gc.TSTRUCT && nl.Type.Funarg != 0 && nl.Type.Type != nil {
-                       loffset -= nl.Type.Type.Width
-               }
-               if nr != nil && nr.Type.Etype == gc.TSTRUCT && nr.Type.Funarg != 0 && nr.Type.Type != nil {
-                       roffset -= nr.Type.Type.Width
-               }
-
-               for t := nl.Type.Type; t != nil; t = t.Down {
-                       nodl.Xoffset = loffset + t.Width
-                       nodl.Type = t.Type
-
-                       if nr == nil {
-                               gc.Clearslim(&nodl)
-                       } else {
-                               nodr.Xoffset = roffset + t.Width
-                               nodr.Type = nodl.Type
-                               gmove(&nodr, &nodl)
-                       }
-               }
-
-               goto yes
-       }
-
-no:
-       if freer != 0 {
-               regfree(&nodr)
-       }
-       if freel != 0 {
-               regfree(&nodl)
-       }
-       return false
-
-yes:
-       if freer != 0 {
-               regfree(&nodr)
-       }
-       if freel != 0 {
-               regfree(&nodl)
-       }
-       return true
-}
index 4b8b82c5612694fe71258a70d80f66775f043535..c565550ab0b4cd5ff2e30d5efe8ae0c5c80ac8c5 100644 (file)
@@ -61,6 +61,7 @@ func main() {
        gc.Thearch.Ginit = ginit
        gc.Thearch.Gins = gins
        gc.Thearch.Ginscall = ginscall
+       gc.Thearch.Gmove = gmove
        gc.Thearch.Igen = igen
        gc.Thearch.Linkarchinit = linkarchinit
        gc.Thearch.Peep = peep
index 353817779a3c38d839ca4000b581ca640949bd92..6eb95010f909f5233e28f18f908b5b3c06a2730f 100644 (file)
@@ -657,7 +657,7 @@ func clearfat(nl *gc.Node) {
        w := uint32(nl.Type.Width)
 
        // Avoid taking the address for simple enough types.
-       if componentgen(nil, nl) {
+       if gc.Componentgen(nil, nl) {
                return
        }
 
index b757232d691202c3a3ddb88120fc45354b4de408..d11f7c7f695818ffa4ff00f1e6a59d3ebc530d84 100644 (file)
@@ -1441,7 +1441,7 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
        }
 
        // Avoid taking the address for simple enough types.
-       if componentgen(n, ns) {
+       if gc.Componentgen(n, ns) {
                return
        }
 
@@ -1612,268 +1612,3 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
 
        restx(&cx, &oldcx)
 }
-
-func cadable(n *gc.Node) bool {
-       if n.Addable == 0 {
-               // dont know how it happens,
-               // but it does
-               return false
-       }
-
-       switch n.Op {
-       case gc.ONAME:
-               return true
-       }
-
-       return false
-}
-
-/*
- * copy a composite value by moving its individual components.
- * Slices, strings and interfaces are supported.
- * Small structs or arrays with elements of basic type are
- * also supported.
- * nr is N when assigning a zero value.
- * return 1 if can do, 0 if can't.
- */
-func componentgen(nr *gc.Node, nl *gc.Node) bool {
-       var nodl gc.Node
-       var nodr gc.Node
-
-       freel := 0
-       freer := 0
-
-       switch nl.Type.Etype {
-       default:
-               goto no
-
-       case gc.TARRAY:
-               t := nl.Type
-
-               // Slices are ok.
-               if gc.Isslice(t) {
-                       break
-               }
-
-               // Small arrays are ok.
-               if t.Bound > 0 && t.Bound <= 3 && !gc.Isfat(t.Type) {
-                       break
-               }
-
-               goto no
-
-               // Small structs with non-fat types are ok.
-       // Zero-sized structs are treated separately elsewhere.
-       case gc.TSTRUCT:
-               fldcount := int64(0)
-
-               for t := nl.Type.Type; t != nil; t = t.Down {
-                       if gc.Isfat(t.Type) && !gc.Isslice(t) {
-                               goto no
-                       }
-                       if t.Etype != gc.TFIELD {
-                               gc.Fatal("componentgen: not a TFIELD: %v", gc.Tconv(t, obj.FmtLong))
-                       }
-                       fldcount++
-               }
-
-               if fldcount == 0 || fldcount > 4 {
-                       goto no
-               }
-
-       case gc.TSTRING,
-               gc.TINTER:
-               break
-       }
-
-       nodl = *nl
-       if !cadable(nl) {
-               if nr != nil && !cadable(nr) {
-                       goto no
-               }
-               igen(nl, &nodl, nil)
-               freel = 1
-       }
-
-       if nr != nil {
-               nodr = *nr
-               if !cadable(nr) {
-                       igen(nr, &nodr, nil)
-                       freer = 1
-               }
-       } else {
-               // When zeroing, prepare a register containing zero.
-               var tmp gc.Node
-               gc.Nodconst(&tmp, nl.Type, 0)
-
-               regalloc(&nodr, gc.Types[gc.TUINT], nil)
-               gmove(&tmp, &nodr)
-               freer = 1
-       }
-
-       // nl and nr are 'cadable' which basically means they are names (variables) now.
-       // If they are the same variable, don't generate any code, because the
-       // VARDEF we generate will mark the old value as dead incorrectly.
-       // (And also the assignments are useless.)
-       if nr != nil && nl.Op == gc.ONAME && nr.Op == gc.ONAME && nl == nr {
-               goto yes
-       }
-
-       switch nl.Type.Etype {
-       // componentgen for arrays.
-       case gc.TARRAY:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               t := nl.Type
-               if !gc.Isslice(t) {
-                       nodl.Type = t.Type
-                       nodr.Type = nodl.Type
-                       for fldcount := int64(0); fldcount < t.Bound; fldcount++ {
-                               if nr == nil {
-                                       gc.Clearslim(&nodl)
-                               } else {
-                                       gmove(&nodr, &nodl)
-                               }
-                               nodl.Xoffset += t.Type.Width
-                               nodr.Xoffset += t.Type.Width
-                       }
-
-                       goto yes
-               }
-
-               // componentgen for slices.
-               nodl.Xoffset += int64(gc.Array_array)
-
-               nodl.Type = gc.Ptrto(nl.Type.Type)
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-               nodl.Type = gc.Types[gc.Simtype[gc.TUINT]]
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_cap) - int64(gc.Array_nel)
-               nodl.Type = gc.Types[gc.Simtype[gc.TUINT]]
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_cap) - int64(gc.Array_nel)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               goto yes
-
-       case gc.TSTRING:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               nodl.Xoffset += int64(gc.Array_array)
-               nodl.Type = gc.Ptrto(gc.Types[gc.TUINT8])
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-               nodl.Type = gc.Types[gc.Simtype[gc.TUINT]]
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               goto yes
-
-       case gc.TINTER:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               nodl.Xoffset += int64(gc.Array_array)
-               nodl.Type = gc.Ptrto(gc.Types[gc.TUINT8])
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-               nodl.Type = gc.Ptrto(gc.Types[gc.TUINT8])
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               goto yes
-
-       case gc.TSTRUCT:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               loffset := nodl.Xoffset
-               roffset := nodr.Xoffset
-
-               // funarg structs may not begin at offset zero.
-               if nl.Type.Etype == gc.TSTRUCT && nl.Type.Funarg != 0 && nl.Type.Type != nil {
-                       loffset -= nl.Type.Type.Width
-               }
-               if nr != nil && nr.Type.Etype == gc.TSTRUCT && nr.Type.Funarg != 0 && nr.Type.Type != nil {
-                       roffset -= nr.Type.Type.Width
-               }
-
-               for t := nl.Type.Type; t != nil; t = t.Down {
-                       nodl.Xoffset = loffset + t.Width
-                       nodl.Type = t.Type
-
-                       if nr == nil {
-                               gc.Clearslim(&nodl)
-                       } else {
-                               nodr.Xoffset = roffset + t.Width
-                               nodr.Type = nodl.Type
-                               gmove(&nodr, &nodl)
-                       }
-               }
-
-               goto yes
-       }
-
-no:
-       if freer != 0 {
-               regfree(&nodr)
-       }
-       if freel != 0 {
-               regfree(&nodl)
-       }
-       return false
-
-yes:
-       if freer != 0 {
-               regfree(&nodr)
-       }
-       if freel != 0 {
-               regfree(&nodl)
-       }
-       return true
-}
index 6a2bac84d8280ca360b0e4addae551c37893ec06..ca8d387c2a1474ab3231f78da67f8e8bf2d195a3 100644 (file)
@@ -86,6 +86,7 @@ func main() {
        gc.Thearch.Ginit = ginit
        gc.Thearch.Gins = gins
        gc.Thearch.Ginscall = ginscall
+       gc.Thearch.Gmove = gmove
        gc.Thearch.Igen = igen
        gc.Thearch.Linkarchinit = linkarchinit
        gc.Thearch.Peep = peep
index f980593948695ed25bc7f380abe5e95e36a3ccd1..42bebf8ca0345577b40a3dd5558c8756bf0aa4ec 100644 (file)
@@ -950,7 +950,7 @@ func clearfat(nl *gc.Node) {
        w := nl.Type.Width
 
        // Avoid taking the address for simple enough types.
-       if componentgen(nil, nl) {
+       if gc.Componentgen(nil, nl) {
                return
        }
 
index 455113bbf242344f8cf2b9a33adc0096c4829985..b18ba5f1780b6b44c50a2262294d6bc633974e6b 100644 (file)
@@ -1424,8 +1424,10 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
        }
 
        // Avoid taking the address for simple enough types.
-       //if(componentgen(n, ns))
-       //      return;
+       //if gc.Componentgen(n, ns) {
+       //      return
+       //}
+
        if w == 0 {
                // evaluate side effects only.
                var dst gc.Node
@@ -1598,268 +1600,3 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
        regfree(&src)
        regfree(&tmp)
 }
-
-func cadable(n *gc.Node) bool {
-       if n.Addable == 0 {
-               // dont know how it happens,
-               // but it does
-               return false
-       }
-
-       switch n.Op {
-       case gc.ONAME:
-               return true
-       }
-
-       return false
-}
-
-/*
- * copy a composite value by moving its individual components.
- * Slices, strings and interfaces are supported.
- * Small structs or arrays with elements of basic type are
- * also supported.
- * nr is N when assigning a zero value.
- * return 1 if can do, 0 if can't.
- */
-func componentgen(nr *gc.Node, nl *gc.Node) bool {
-       var nodl gc.Node
-       var nodr gc.Node
-
-       freel := 0
-       freer := 0
-
-       switch nl.Type.Etype {
-       default:
-               goto no
-
-       case gc.TARRAY:
-               t := nl.Type
-
-               // Slices are ok.
-               if gc.Isslice(t) {
-                       break
-               }
-
-               // Small arrays are ok.
-               if t.Bound > 0 && t.Bound <= 3 && !gc.Isfat(t.Type) {
-                       break
-               }
-
-               goto no
-
-               // Small structs with non-fat types are ok.
-       // Zero-sized structs are treated separately elsewhere.
-       case gc.TSTRUCT:
-               fldcount := int64(0)
-
-               for t := nl.Type.Type; t != nil; t = t.Down {
-                       if gc.Isfat(t.Type) {
-                               goto no
-                       }
-                       if t.Etype != gc.TFIELD {
-                               gc.Fatal("componentgen: not a TFIELD: %v", gc.Tconv(t, obj.FmtLong))
-                       }
-                       fldcount++
-               }
-
-               if fldcount == 0 || fldcount > 4 {
-                       goto no
-               }
-
-       case gc.TSTRING,
-               gc.TINTER:
-               break
-       }
-
-       nodl = *nl
-       if !cadable(nl) {
-               if nr != nil && !cadable(nr) {
-                       goto no
-               }
-               igen(nl, &nodl, nil)
-               freel = 1
-       }
-
-       if nr != nil {
-               nodr = *nr
-               if !cadable(nr) {
-                       igen(nr, &nodr, nil)
-                       freer = 1
-               }
-       } else {
-               // When zeroing, prepare a register containing zero.
-               var tmp gc.Node
-               gc.Nodconst(&tmp, nl.Type, 0)
-
-               regalloc(&nodr, gc.Types[gc.TUINT], nil)
-               gmove(&tmp, &nodr)
-               freer = 1
-       }
-
-       // nl and nr are 'cadable' which basically means they are names (variables) now.
-       // If they are the same variable, don't generate any code, because the
-       // VARDEF we generate will mark the old value as dead incorrectly.
-       // (And also the assignments are useless.)
-       if nr != nil && nl.Op == gc.ONAME && nr.Op == gc.ONAME && nl == nr {
-               goto yes
-       }
-
-       switch nl.Type.Etype {
-       // componentgen for arrays.
-       case gc.TARRAY:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               t := nl.Type
-               if !gc.Isslice(t) {
-                       nodl.Type = t.Type
-                       nodr.Type = nodl.Type
-                       for fldcount := int64(0); fldcount < t.Bound; fldcount++ {
-                               if nr == nil {
-                                       gc.Clearslim(&nodl)
-                               } else {
-                                       gmove(&nodr, &nodl)
-                               }
-                               nodl.Xoffset += t.Type.Width
-                               nodr.Xoffset += t.Type.Width
-                       }
-
-                       goto yes
-               }
-
-               // componentgen for slices.
-               nodl.Xoffset += int64(gc.Array_array)
-
-               nodl.Type = gc.Ptrto(nl.Type.Type)
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-               nodl.Type = gc.Types[gc.Simtype[gc.TUINT]]
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_cap) - int64(gc.Array_nel)
-               nodl.Type = gc.Types[gc.Simtype[gc.TUINT]]
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_cap) - int64(gc.Array_nel)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               goto yes
-
-       case gc.TSTRING:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               nodl.Xoffset += int64(gc.Array_array)
-               nodl.Type = gc.Ptrto(gc.Types[gc.TUINT8])
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-               nodl.Type = gc.Types[gc.Simtype[gc.TUINT]]
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               goto yes
-
-       case gc.TINTER:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               nodl.Xoffset += int64(gc.Array_array)
-               nodl.Type = gc.Ptrto(gc.Types[gc.TUINT8])
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-               nodl.Type = gc.Ptrto(gc.Types[gc.TUINT8])
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               goto yes
-
-       case gc.TSTRUCT:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               loffset := nodl.Xoffset
-               roffset := nodr.Xoffset
-
-               // funarg structs may not begin at offset zero.
-               if nl.Type.Etype == gc.TSTRUCT && nl.Type.Funarg != 0 && nl.Type.Type != nil {
-                       loffset -= nl.Type.Type.Width
-               }
-               if nr != nil && nr.Type.Etype == gc.TSTRUCT && nr.Type.Funarg != 0 && nr.Type.Type != nil {
-                       roffset -= nr.Type.Type.Width
-               }
-
-               for t := nl.Type.Type; t != nil; t = t.Down {
-                       nodl.Xoffset = loffset + t.Width
-                       nodl.Type = t.Type
-
-                       if nr == nil {
-                               gc.Clearslim(&nodl)
-                       } else {
-                               nodr.Xoffset = roffset + t.Width
-                               nodr.Type = nodl.Type
-                               gmove(&nodr, &nodl)
-                       }
-               }
-
-               goto yes
-       }
-
-no:
-       if freer != 0 {
-               regfree(&nodr)
-       }
-       if freel != 0 {
-               regfree(&nodl)
-       }
-       return false
-
-yes:
-       if freer != 0 {
-               regfree(&nodr)
-       }
-       if freel != 0 {
-               regfree(&nodl)
-       }
-       return true
-}
index 52ac23c39a3cac3e5989058bb6e97686261dd42c..19c4d386fae14b9f62b85c6425de79719b01dba4 100644 (file)
@@ -60,6 +60,7 @@ func main() {
        gc.Thearch.Ginit = ginit
        gc.Thearch.Gins = gins
        gc.Thearch.Ginscall = ginscall
+       gc.Thearch.Gmove = gmove
        gc.Thearch.Igen = igen
        gc.Thearch.Linkarchinit = linkarchinit
        gc.Thearch.Peep = peep
index 7eb913f22be5d74a96aa2090d14aa5d1d2d5423b..cb486639e239ad992ed39a9626509dd464099719 100644 (file)
@@ -720,8 +720,9 @@ func clearfat(nl *gc.Node) {
        w := uint64(uint64(nl.Type.Width))
 
        // Avoid taking the address for simple enough types.
-       //if(componentgen(N, nl))
-       //      return;
+       //if gc.Componentgen(nil, nl) {
+       //      return
+       //}
 
        c := uint64(w % 8) // bytes
        q := uint64(w / 8) // dwords
index aefae7ed85b5e3426fb25aab84c802ac45650430..2a10e49bd4c44c6e68b1d5ecb09631d610682321 100644 (file)
@@ -1332,7 +1332,7 @@ func sgen(n *gc.Node, res *gc.Node, w int64) {
        }
 
        // Avoid taking the address for simple enough types.
-       if componentgen(n, res) {
+       if gc.Componentgen(n, res) {
                return
        }
 
@@ -1462,268 +1462,3 @@ func sgen(n *gc.Node, res *gc.Node, w int64) {
                }
        }
 }
-
-func cadable(n *gc.Node) bool {
-       if n.Addable == 0 {
-               // dont know how it happens,
-               // but it does
-               return false
-       }
-
-       switch n.Op {
-       case gc.ONAME:
-               return true
-       }
-
-       return false
-}
-
-/*
- * copy a composite value by moving its individual components.
- * Slices, strings and interfaces are supported.
- * Small structs or arrays with elements of basic type are
- * also supported.
- * nr is N when assigning a zero value.
- * return 1 if can do, 0 if can't.
- */
-func componentgen(nr *gc.Node, nl *gc.Node) bool {
-       var nodl gc.Node
-       var nodr gc.Node
-
-       freel := 0
-       freer := 0
-
-       switch nl.Type.Etype {
-       default:
-               goto no
-
-       case gc.TARRAY:
-               t := nl.Type
-
-               // Slices are ok.
-               if gc.Isslice(t) {
-                       break
-               }
-
-               // Small arrays are ok.
-               if t.Bound > 0 && t.Bound <= 3 && !gc.Isfat(t.Type) {
-                       break
-               }
-
-               goto no
-
-               // Small structs with non-fat types are ok.
-       // Zero-sized structs are treated separately elsewhere.
-       case gc.TSTRUCT:
-               fldcount := int64(0)
-
-               for t := nl.Type.Type; t != nil; t = t.Down {
-                       if gc.Isfat(t.Type) {
-                               goto no
-                       }
-                       if t.Etype != gc.TFIELD {
-                               gc.Fatal("componentgen: not a TFIELD: %v", gc.Tconv(t, obj.FmtLong))
-                       }
-                       fldcount++
-               }
-
-               if fldcount == 0 || fldcount > 4 {
-                       goto no
-               }
-
-       case gc.TSTRING,
-               gc.TINTER:
-               break
-       }
-
-       nodl = *nl
-       if !cadable(nl) {
-               if nr != nil && !cadable(nr) {
-                       goto no
-               }
-               igen(nl, &nodl, nil)
-               freel = 1
-       }
-
-       if nr != nil {
-               nodr = *nr
-               if !cadable(nr) {
-                       igen(nr, &nodr, nil)
-                       freer = 1
-               }
-       } else {
-               // When zeroing, prepare a register containing zero.
-               var tmp gc.Node
-               gc.Nodconst(&tmp, nl.Type, 0)
-
-               regalloc(&nodr, gc.Types[gc.TUINT], nil)
-               gmove(&tmp, &nodr)
-               freer = 1
-       }
-
-       // nl and nr are 'cadable' which basically means they are names (variables) now.
-       // If they are the same variable, don't generate any code, because the
-       // VARDEF we generate will mark the old value as dead incorrectly.
-       // (And also the assignments are useless.)
-       if nr != nil && nl.Op == gc.ONAME && nr.Op == gc.ONAME && nl == nr {
-               goto yes
-       }
-
-       switch nl.Type.Etype {
-       // componentgen for arrays.
-       case gc.TARRAY:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               t := nl.Type
-               if !gc.Isslice(t) {
-                       nodl.Type = t.Type
-                       nodr.Type = nodl.Type
-                       for fldcount := int64(0); fldcount < t.Bound; fldcount++ {
-                               if nr == nil {
-                                       gc.Clearslim(&nodl)
-                               } else {
-                                       gmove(&nodr, &nodl)
-                               }
-                               nodl.Xoffset += t.Type.Width
-                               nodr.Xoffset += t.Type.Width
-                       }
-
-                       goto yes
-               }
-
-               // componentgen for slices.
-               nodl.Xoffset += int64(gc.Array_array)
-
-               nodl.Type = gc.Ptrto(nl.Type.Type)
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-               nodl.Type = gc.Types[gc.Simtype[gc.TUINT]]
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_cap) - int64(gc.Array_nel)
-               nodl.Type = gc.Types[gc.Simtype[gc.TUINT]]
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_cap) - int64(gc.Array_nel)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               goto yes
-
-       case gc.TSTRING:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               nodl.Xoffset += int64(gc.Array_array)
-               nodl.Type = gc.Ptrto(gc.Types[gc.TUINT8])
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-               nodl.Type = gc.Types[gc.Simtype[gc.TUINT]]
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               goto yes
-
-       case gc.TINTER:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               nodl.Xoffset += int64(gc.Array_array)
-               nodl.Type = gc.Ptrto(gc.Types[gc.TUINT8])
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-               nodl.Type = gc.Ptrto(gc.Types[gc.TUINT8])
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               goto yes
-
-       case gc.TSTRUCT:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               loffset := nodl.Xoffset
-               roffset := nodr.Xoffset
-
-               // funarg structs may not begin at offset zero.
-               if nl.Type.Etype == gc.TSTRUCT && nl.Type.Funarg != 0 && nl.Type.Type != nil {
-                       loffset -= nl.Type.Type.Width
-               }
-               if nr != nil && nr.Type.Etype == gc.TSTRUCT && nr.Type.Funarg != 0 && nr.Type.Type != nil {
-                       roffset -= nr.Type.Type.Width
-               }
-
-               for t := nl.Type.Type; t != nil; t = t.Down {
-                       nodl.Xoffset = loffset + t.Width
-                       nodl.Type = t.Type
-
-                       if nr == nil {
-                               gc.Clearslim(&nodl)
-                       } else {
-                               nodr.Xoffset = roffset + t.Width
-                               nodr.Type = nodl.Type
-                               gmove(&nodr, &nodl)
-                       }
-               }
-
-               goto yes
-       }
-
-no:
-       if freer != 0 {
-               regfree(&nodr)
-       }
-       if freel != 0 {
-               regfree(&nodl)
-       }
-       return false
-
-yes:
-       if freer != 0 {
-               regfree(&nodr)
-       }
-       if freel != 0 {
-               regfree(&nodl)
-       }
-       return true
-}
index 7c462f521f4513a6a1cb826d3cab4ad7da9de293..f0c878aed4b6d9d2d59c7a24d2a4afd54c63aef0 100644 (file)
@@ -61,6 +61,7 @@ func main() {
        gc.Thearch.Ginit = ginit
        gc.Thearch.Gins = gins
        gc.Thearch.Ginscall = ginscall
+       gc.Thearch.Gmove = gmove
        gc.Thearch.Igen = igen
        gc.Thearch.Linkarchinit = linkarchinit
        gc.Thearch.Peep = peep
index 077b6579bb97fa8e1a72a40a6e25fed68b8c5046..3a197cd931a3881966d3b374ff2365473244f840 100644 (file)
@@ -112,7 +112,7 @@ func clearfat(nl *gc.Node) {
        w := uint32(nl.Type.Width)
 
        // Avoid taking the address for simple enough types.
-       if componentgen(nil, nl) {
+       if gc.Componentgen(nil, nl) {
                return
        }
 
index 4ab5215e552dcf9b0ddc4193434d710af8d9d8b3..6ab7f35dd0cf650a1b4804e5bd660efc6eb085dc 100644 (file)
@@ -1445,8 +1445,10 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
        }
 
        // Avoid taking the address for simple enough types.
-       //if(componentgen(n, ns))
-       //      return;
+       if gc.Componentgen(n, ns) {
+               return
+       }
+
        if w == 0 {
                // evaluate side effects only.
                var dst gc.Node
@@ -1615,268 +1617,3 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
        regfree(&src)
        regfree(&tmp)
 }
-
-func cadable(n *gc.Node) bool {
-       if n.Addable == 0 {
-               // dont know how it happens,
-               // but it does
-               return false
-       }
-
-       switch n.Op {
-       case gc.ONAME:
-               return true
-       }
-
-       return false
-}
-
-/*
- * copy a composite value by moving its individual components.
- * Slices, strings and interfaces are supported.
- * Small structs or arrays with elements of basic type are
- * also supported.
- * nr is N when assigning a zero value.
- * return 1 if can do, 0 if can't.
- */
-func componentgen(nr *gc.Node, nl *gc.Node) bool {
-       var nodl gc.Node
-       var nodr gc.Node
-
-       freel := 0
-       freer := 0
-
-       switch nl.Type.Etype {
-       default:
-               goto no
-
-       case gc.TARRAY:
-               t := nl.Type
-
-               // Slices are ok.
-               if gc.Isslice(t) {
-                       break
-               }
-
-               // Small arrays are ok.
-               if t.Bound > 0 && t.Bound <= 3 && !gc.Isfat(t.Type) {
-                       break
-               }
-
-               goto no
-
-               // Small structs with non-fat types are ok.
-       // Zero-sized structs are treated separately elsewhere.
-       case gc.TSTRUCT:
-               fldcount := int64(0)
-
-               for t := nl.Type.Type; t != nil; t = t.Down {
-                       if gc.Isfat(t.Type) {
-                               goto no
-                       }
-                       if t.Etype != gc.TFIELD {
-                               gc.Fatal("componentgen: not a TFIELD: %v", gc.Tconv(t, obj.FmtLong))
-                       }
-                       fldcount++
-               }
-
-               if fldcount == 0 || fldcount > 4 {
-                       goto no
-               }
-
-       case gc.TSTRING,
-               gc.TINTER:
-               break
-       }
-
-       nodl = *nl
-       if !cadable(nl) {
-               if nr != nil && !cadable(nr) {
-                       goto no
-               }
-               igen(nl, &nodl, nil)
-               freel = 1
-       }
-
-       if nr != nil {
-               nodr = *nr
-               if !cadable(nr) {
-                       igen(nr, &nodr, nil)
-                       freer = 1
-               }
-       } else {
-               // When zeroing, prepare a register containing zero.
-               var tmp gc.Node
-               gc.Nodconst(&tmp, nl.Type, 0)
-
-               regalloc(&nodr, gc.Types[gc.TUINT], nil)
-               gmove(&tmp, &nodr)
-               freer = 1
-       }
-
-       // nl and nr are 'cadable' which basically means they are names (variables) now.
-       // If they are the same variable, don't generate any code, because the
-       // VARDEF we generate will mark the old value as dead incorrectly.
-       // (And also the assignments are useless.)
-       if nr != nil && nl.Op == gc.ONAME && nr.Op == gc.ONAME && nl == nr {
-               goto yes
-       }
-
-       switch nl.Type.Etype {
-       // componentgen for arrays.
-       case gc.TARRAY:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               t := nl.Type
-               if !gc.Isslice(t) {
-                       nodl.Type = t.Type
-                       nodr.Type = nodl.Type
-                       for fldcount := int64(0); fldcount < t.Bound; fldcount++ {
-                               if nr == nil {
-                                       gc.Clearslim(&nodl)
-                               } else {
-                                       gmove(&nodr, &nodl)
-                               }
-                               nodl.Xoffset += t.Type.Width
-                               nodr.Xoffset += t.Type.Width
-                       }
-
-                       goto yes
-               }
-
-               // componentgen for slices.
-               nodl.Xoffset += int64(gc.Array_array)
-
-               nodl.Type = gc.Ptrto(nl.Type.Type)
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-               nodl.Type = gc.Types[gc.Simtype[gc.TUINT]]
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_cap) - int64(gc.Array_nel)
-               nodl.Type = gc.Types[gc.Simtype[gc.TUINT]]
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_cap) - int64(gc.Array_nel)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               goto yes
-
-       case gc.TSTRING:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               nodl.Xoffset += int64(gc.Array_array)
-               nodl.Type = gc.Ptrto(gc.Types[gc.TUINT8])
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-               nodl.Type = gc.Types[gc.Simtype[gc.TUINT]]
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               goto yes
-
-       case gc.TINTER:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               nodl.Xoffset += int64(gc.Array_array)
-               nodl.Type = gc.Ptrto(gc.Types[gc.TUINT8])
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               nodl.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-               nodl.Type = gc.Ptrto(gc.Types[gc.TUINT8])
-
-               if nr != nil {
-                       nodr.Xoffset += int64(gc.Array_nel) - int64(gc.Array_array)
-                       nodr.Type = nodl.Type
-               }
-
-               gmove(&nodr, &nodl)
-
-               goto yes
-
-       case gc.TSTRUCT:
-               if nl.Op == gc.ONAME {
-                       gc.Gvardef(nl)
-               }
-               loffset := nodl.Xoffset
-               roffset := nodr.Xoffset
-
-               // funarg structs may not begin at offset zero.
-               if nl.Type.Etype == gc.TSTRUCT && nl.Type.Funarg != 0 && nl.Type.Type != nil {
-                       loffset -= nl.Type.Type.Width
-               }
-               if nr != nil && nr.Type.Etype == gc.TSTRUCT && nr.Type.Funarg != 0 && nr.Type.Type != nil {
-                       roffset -= nr.Type.Type.Width
-               }
-
-               for t := nl.Type.Type; t != nil; t = t.Down {
-                       nodl.Xoffset = loffset + t.Width
-                       nodl.Type = t.Type
-
-                       if nr == nil {
-                               gc.Clearslim(&nodl)
-                       } else {
-                               nodr.Xoffset = roffset + t.Width
-                               nodr.Type = nodl.Type
-                               gmove(&nodr, &nodl)
-                       }
-               }
-
-               goto yes
-       }
-
-no:
-       if freer != 0 {
-               regfree(&nodr)
-       }
-       if freel != 0 {
-               regfree(&nodl)
-       }
-       return false
-
-yes:
-       if freer != 0 {
-               regfree(&nodr)
-       }
-       if freel != 0 {
-               regfree(&nodl)
-       }
-       return true
-}
index b39149a95217577a593a04f5f32efb906d1c58e3..69e6bac334126bd452d766722ce13bbbd40f9a25 100644 (file)
@@ -69,6 +69,7 @@ func main() {
        gc.Thearch.Ginit = ginit
        gc.Thearch.Gins = gins
        gc.Thearch.Ginscall = ginscall
+       gc.Thearch.Gmove = gmove
        gc.Thearch.Igen = igen
        gc.Thearch.Linkarchinit = linkarchinit
        gc.Thearch.Peep = peep
index 5919a7911391e792e04fdeaaed83f78123d5aa38..dfc54a78d50d0d66d81455de35f06dc0b680122c 100644 (file)
@@ -734,8 +734,9 @@ func clearfat(nl *gc.Node) {
        w := uint64(uint64(nl.Type.Width))
 
        // Avoid taking the address for simple enough types.
-       //if(componentgen(N, nl))
-       //      return;
+       if gc.Componentgen(nil, nl) {
+               return
+       }
 
        c := uint64(w % 8) // bytes
        q := uint64(w / 8) // dwords
index 3777cc310dee35941982f3ddccd65d4b28208208..314f6c1117e70bc97b2b63ef256ac6ae94585174 100644 (file)
@@ -956,3 +956,268 @@ func checklabels() {
                }
        }
 }
+
+/*
+ * copy a composite value by moving its individual components.
+ * Slices, strings and interfaces are supported.
+ * Small structs or arrays with elements of basic type are
+ * also supported.
+ * nr is N when assigning a zero value.
+ * return 1 if can do, 0 if can't.
+ */
+func Componentgen(nr *Node, nl *Node) bool {
+       var nodl Node
+       var nodr Node
+
+       freel := 0
+       freer := 0
+
+       switch nl.Type.Etype {
+       default:
+               goto no
+
+       case TARRAY:
+               t := nl.Type
+
+               // Slices are ok.
+               if Isslice(t) {
+                       break
+               }
+
+               // Small arrays are ok.
+               if t.Bound > 0 && t.Bound <= 3 && !Isfat(t.Type) {
+                       break
+               }
+
+               goto no
+
+               // Small structs with non-fat types are ok.
+       // Zero-sized structs are treated separately elsewhere.
+       case TSTRUCT:
+               fldcount := int64(0)
+
+               for t := nl.Type.Type; t != nil; t = t.Down {
+                       if Isfat(t.Type) && !Isslice(t) {
+                               goto no
+                       }
+                       if t.Etype != TFIELD {
+                               Fatal("componentgen: not a TFIELD: %v", Tconv(t, obj.FmtLong))
+                       }
+                       fldcount++
+               }
+
+               if fldcount == 0 || fldcount > 4 {
+                       goto no
+               }
+
+       case TSTRING,
+               TINTER:
+               break
+       }
+
+       nodl = *nl
+       if !cadable(nl) {
+               if nr != nil && !cadable(nr) {
+                       goto no
+               }
+               Thearch.Igen(nl, &nodl, nil)
+               freel = 1
+       }
+
+       if nr != nil {
+               nodr = *nr
+               if !cadable(nr) {
+                       Thearch.Igen(nr, &nodr, nil)
+                       freer = 1
+               }
+       } else {
+               // When zeroing, prepare a register containing zero.
+               var tmp Node
+               Nodconst(&tmp, nl.Type, 0)
+
+               Thearch.Regalloc(&nodr, Types[TUINT], nil)
+               Thearch.Gmove(&tmp, &nodr)
+               freer = 1
+       }
+
+       // nl and nr are 'cadable' which basically means they are names (variables) now.
+       // If they are the same variable, don't generate any code, because the
+       // VARDEF we generate will mark the old value as dead incorrectly.
+       // (And also the assignments are useless.)
+       if nr != nil && nl.Op == ONAME && nr.Op == ONAME && nl == nr {
+               goto yes
+       }
+
+       switch nl.Type.Etype {
+       // componentgen for arrays.
+       case TARRAY:
+               if nl.Op == ONAME {
+                       Gvardef(nl)
+               }
+               t := nl.Type
+               if !Isslice(t) {
+                       nodl.Type = t.Type
+                       nodr.Type = nodl.Type
+                       for fldcount := int64(0); fldcount < t.Bound; fldcount++ {
+                               if nr == nil {
+                                       Clearslim(&nodl)
+                               } else {
+                                       Thearch.Gmove(&nodr, &nodl)
+                               }
+                               nodl.Xoffset += t.Type.Width
+                               nodr.Xoffset += t.Type.Width
+                       }
+
+                       goto yes
+               }
+
+               // componentgen for slices.
+               nodl.Xoffset += int64(Array_array)
+
+               nodl.Type = Ptrto(nl.Type.Type)
+
+               if nr != nil {
+                       nodr.Xoffset += int64(Array_array)
+                       nodr.Type = nodl.Type
+               }
+
+               Thearch.Gmove(&nodr, &nodl)
+
+               nodl.Xoffset += int64(Array_nel) - int64(Array_array)
+               nodl.Type = Types[Simtype[TUINT]]
+
+               if nr != nil {
+                       nodr.Xoffset += int64(Array_nel) - int64(Array_array)
+                       nodr.Type = nodl.Type
+               }
+
+               Thearch.Gmove(&nodr, &nodl)
+
+               nodl.Xoffset += int64(Array_cap) - int64(Array_nel)
+               nodl.Type = Types[Simtype[TUINT]]
+
+               if nr != nil {
+                       nodr.Xoffset += int64(Array_cap) - int64(Array_nel)
+                       nodr.Type = nodl.Type
+               }
+
+               Thearch.Gmove(&nodr, &nodl)
+
+               goto yes
+
+       case TSTRING:
+               if nl.Op == ONAME {
+                       Gvardef(nl)
+               }
+               nodl.Xoffset += int64(Array_array)
+               nodl.Type = Ptrto(Types[TUINT8])
+
+               if nr != nil {
+                       nodr.Xoffset += int64(Array_array)
+                       nodr.Type = nodl.Type
+               }
+
+               Thearch.Gmove(&nodr, &nodl)
+
+               nodl.Xoffset += int64(Array_nel) - int64(Array_array)
+               nodl.Type = Types[Simtype[TUINT]]
+
+               if nr != nil {
+                       nodr.Xoffset += int64(Array_nel) - int64(Array_array)
+                       nodr.Type = nodl.Type
+               }
+
+               Thearch.Gmove(&nodr, &nodl)
+
+               goto yes
+
+       case TINTER:
+               if nl.Op == ONAME {
+                       Gvardef(nl)
+               }
+               nodl.Xoffset += int64(Array_array)
+               nodl.Type = Ptrto(Types[TUINT8])
+
+               if nr != nil {
+                       nodr.Xoffset += int64(Array_array)
+                       nodr.Type = nodl.Type
+               }
+
+               Thearch.Gmove(&nodr, &nodl)
+
+               nodl.Xoffset += int64(Array_nel) - int64(Array_array)
+               nodl.Type = Ptrto(Types[TUINT8])
+
+               if nr != nil {
+                       nodr.Xoffset += int64(Array_nel) - int64(Array_array)
+                       nodr.Type = nodl.Type
+               }
+
+               Thearch.Gmove(&nodr, &nodl)
+
+               goto yes
+
+       case TSTRUCT:
+               if nl.Op == ONAME {
+                       Gvardef(nl)
+               }
+               loffset := nodl.Xoffset
+               roffset := nodr.Xoffset
+
+               // funarg structs may not begin at offset zero.
+               if nl.Type.Etype == TSTRUCT && nl.Type.Funarg != 0 && nl.Type.Type != nil {
+                       loffset -= nl.Type.Type.Width
+               }
+               if nr != nil && nr.Type.Etype == TSTRUCT && nr.Type.Funarg != 0 && nr.Type.Type != nil {
+                       roffset -= nr.Type.Type.Width
+               }
+
+               for t := nl.Type.Type; t != nil; t = t.Down {
+                       nodl.Xoffset = loffset + t.Width
+                       nodl.Type = t.Type
+
+                       if nr == nil {
+                               Clearslim(&nodl)
+                       } else {
+                               nodr.Xoffset = roffset + t.Width
+                               nodr.Type = nodl.Type
+                               Thearch.Gmove(&nodr, &nodl)
+                       }
+               }
+
+               goto yes
+       }
+
+no:
+       if freer != 0 {
+               Thearch.Regfree(&nodr)
+       }
+       if freel != 0 {
+               Thearch.Regfree(&nodl)
+       }
+       return false
+
+yes:
+       if freer != 0 {
+               Thearch.Regfree(&nodr)
+       }
+       if freel != 0 {
+               Thearch.Regfree(&nodl)
+       }
+       return true
+}
+
+func cadable(n *Node) bool {
+       if n.Addable == 0 {
+               // dont know how it happens,
+               // but it does
+               return false
+       }
+
+       switch n.Op {
+       case ONAME:
+               return true
+       }
+
+       return false
+}
index e33b6f5e73ec645084367566707ef78418e413e6..67a226e728016e2302346574ef61061c47e548c3 100644 (file)
@@ -790,6 +790,7 @@ type Arch struct {
        Ginit          func()
        Gins           func(int, *Node, *Node) *obj.Prog
        Ginscall       func(*Node, int)
+       Gmove          func(*Node, *Node)
        Igen           func(*Node, *Node, *Node)
        Linkarchinit   func()
        Peep           func(*obj.Prog)