mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00: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
17 changed files with 291 additions and 1339 deletions
|
|
@ -1530,7 +1530,7 @@ func sgen(n *gc.Node, res *gc.Node, w int64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid taking the address for simple enough types.
|
// Avoid taking the address for simple enough types.
|
||||||
if componentgen(n, res) {
|
if gc.Componentgen(n, res) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1725,268 +1725,3 @@ func sgen(n *gc.Node, res *gc.Node, w int64) {
|
||||||
regfree(&src)
|
regfree(&src)
|
||||||
regfree(&tmp)
|
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.Ginit = ginit
|
||||||
gc.Thearch.Gins = gins
|
gc.Thearch.Gins = gins
|
||||||
gc.Thearch.Ginscall = ginscall
|
gc.Thearch.Ginscall = ginscall
|
||||||
|
gc.Thearch.Gmove = gmove
|
||||||
gc.Thearch.Igen = igen
|
gc.Thearch.Igen = igen
|
||||||
gc.Thearch.Linkarchinit = linkarchinit
|
gc.Thearch.Linkarchinit = linkarchinit
|
||||||
gc.Thearch.Peep = peep
|
gc.Thearch.Peep = peep
|
||||||
|
|
|
||||||
|
|
@ -657,7 +657,7 @@ func clearfat(nl *gc.Node) {
|
||||||
w := uint32(nl.Type.Width)
|
w := uint32(nl.Type.Width)
|
||||||
|
|
||||||
// Avoid taking the address for simple enough types.
|
// Avoid taking the address for simple enough types.
|
||||||
if componentgen(nil, nl) {
|
if gc.Componentgen(nil, nl) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1441,7 +1441,7 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid taking the address for simple enough types.
|
// Avoid taking the address for simple enough types.
|
||||||
if componentgen(n, ns) {
|
if gc.Componentgen(n, ns) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1612,268 +1612,3 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
|
||||||
|
|
||||||
restx(&cx, &oldcx)
|
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.Ginit = ginit
|
||||||
gc.Thearch.Gins = gins
|
gc.Thearch.Gins = gins
|
||||||
gc.Thearch.Ginscall = ginscall
|
gc.Thearch.Ginscall = ginscall
|
||||||
|
gc.Thearch.Gmove = gmove
|
||||||
gc.Thearch.Igen = igen
|
gc.Thearch.Igen = igen
|
||||||
gc.Thearch.Linkarchinit = linkarchinit
|
gc.Thearch.Linkarchinit = linkarchinit
|
||||||
gc.Thearch.Peep = peep
|
gc.Thearch.Peep = peep
|
||||||
|
|
|
||||||
|
|
@ -950,7 +950,7 @@ func clearfat(nl *gc.Node) {
|
||||||
w := nl.Type.Width
|
w := nl.Type.Width
|
||||||
|
|
||||||
// Avoid taking the address for simple enough types.
|
// Avoid taking the address for simple enough types.
|
||||||
if componentgen(nil, nl) {
|
if gc.Componentgen(nil, nl) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1424,8 +1424,10 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid taking the address for simple enough types.
|
// Avoid taking the address for simple enough types.
|
||||||
//if(componentgen(n, ns))
|
//if gc.Componentgen(n, ns) {
|
||||||
// return;
|
// return
|
||||||
|
//}
|
||||||
|
|
||||||
if w == 0 {
|
if w == 0 {
|
||||||
// evaluate side effects only.
|
// evaluate side effects only.
|
||||||
var dst gc.Node
|
var dst gc.Node
|
||||||
|
|
@ -1598,268 +1600,3 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
|
||||||
regfree(&src)
|
regfree(&src)
|
||||||
regfree(&tmp)
|
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.Ginit = ginit
|
||||||
gc.Thearch.Gins = gins
|
gc.Thearch.Gins = gins
|
||||||
gc.Thearch.Ginscall = ginscall
|
gc.Thearch.Ginscall = ginscall
|
||||||
|
gc.Thearch.Gmove = gmove
|
||||||
gc.Thearch.Igen = igen
|
gc.Thearch.Igen = igen
|
||||||
gc.Thearch.Linkarchinit = linkarchinit
|
gc.Thearch.Linkarchinit = linkarchinit
|
||||||
gc.Thearch.Peep = peep
|
gc.Thearch.Peep = peep
|
||||||
|
|
|
||||||
|
|
@ -720,8 +720,9 @@ func clearfat(nl *gc.Node) {
|
||||||
w := uint64(uint64(nl.Type.Width))
|
w := uint64(uint64(nl.Type.Width))
|
||||||
|
|
||||||
// Avoid taking the address for simple enough types.
|
// Avoid taking the address for simple enough types.
|
||||||
//if(componentgen(N, nl))
|
//if gc.Componentgen(nil, nl) {
|
||||||
// return;
|
// return
|
||||||
|
//}
|
||||||
|
|
||||||
c := uint64(w % 8) // bytes
|
c := uint64(w % 8) // bytes
|
||||||
q := uint64(w / 8) // dwords
|
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.
|
// Avoid taking the address for simple enough types.
|
||||||
if componentgen(n, res) {
|
if gc.Componentgen(n, res) {
|
||||||
return
|
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.Ginit = ginit
|
||||||
gc.Thearch.Gins = gins
|
gc.Thearch.Gins = gins
|
||||||
gc.Thearch.Ginscall = ginscall
|
gc.Thearch.Ginscall = ginscall
|
||||||
|
gc.Thearch.Gmove = gmove
|
||||||
gc.Thearch.Igen = igen
|
gc.Thearch.Igen = igen
|
||||||
gc.Thearch.Linkarchinit = linkarchinit
|
gc.Thearch.Linkarchinit = linkarchinit
|
||||||
gc.Thearch.Peep = peep
|
gc.Thearch.Peep = peep
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ func clearfat(nl *gc.Node) {
|
||||||
w := uint32(nl.Type.Width)
|
w := uint32(nl.Type.Width)
|
||||||
|
|
||||||
// Avoid taking the address for simple enough types.
|
// Avoid taking the address for simple enough types.
|
||||||
if componentgen(nil, nl) {
|
if gc.Componentgen(nil, nl) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1445,8 +1445,10 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid taking the address for simple enough types.
|
// Avoid taking the address for simple enough types.
|
||||||
//if(componentgen(n, ns))
|
if gc.Componentgen(n, ns) {
|
||||||
// return;
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if w == 0 {
|
if w == 0 {
|
||||||
// evaluate side effects only.
|
// evaluate side effects only.
|
||||||
var dst gc.Node
|
var dst gc.Node
|
||||||
|
|
@ -1615,268 +1617,3 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
|
||||||
regfree(&src)
|
regfree(&src)
|
||||||
regfree(&tmp)
|
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.Ginit = ginit
|
||||||
gc.Thearch.Gins = gins
|
gc.Thearch.Gins = gins
|
||||||
gc.Thearch.Ginscall = ginscall
|
gc.Thearch.Ginscall = ginscall
|
||||||
|
gc.Thearch.Gmove = gmove
|
||||||
gc.Thearch.Igen = igen
|
gc.Thearch.Igen = igen
|
||||||
gc.Thearch.Linkarchinit = linkarchinit
|
gc.Thearch.Linkarchinit = linkarchinit
|
||||||
gc.Thearch.Peep = peep
|
gc.Thearch.Peep = peep
|
||||||
|
|
|
||||||
|
|
@ -734,8 +734,9 @@ func clearfat(nl *gc.Node) {
|
||||||
w := uint64(uint64(nl.Type.Width))
|
w := uint64(uint64(nl.Type.Width))
|
||||||
|
|
||||||
// Avoid taking the address for simple enough types.
|
// Avoid taking the address for simple enough types.
|
||||||
//if(componentgen(N, nl))
|
if gc.Componentgen(nil, nl) {
|
||||||
// return;
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c := uint64(w % 8) // bytes
|
c := uint64(w % 8) // bytes
|
||||||
q := uint64(w / 8) // dwords
|
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()
|
Ginit func()
|
||||||
Gins func(int, *Node, *Node) *obj.Prog
|
Gins func(int, *Node, *Node) *obj.Prog
|
||||||
Ginscall func(*Node, int)
|
Ginscall func(*Node, int)
|
||||||
|
Gmove func(*Node, *Node)
|
||||||
Igen func(*Node, *Node, *Node)
|
Igen func(*Node, *Node, *Node)
|
||||||
Linkarchinit func()
|
Linkarchinit func()
|
||||||
Peep func(*obj.Prog)
|
Peep func(*obj.Prog)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue