mirror of
https://github.com/golang/go
synced 2024-11-12 04:00:23 -07:00
cmd/internal/gc: move componentgen into portable code
Change-Id: I652cc7a33a186d1041f62f6e7581421496832a27 Reviewed-on: https://go-review.googlesource.com/7747 Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
parent
d47fe8092e
commit
b960263244
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user