mirror of
https://github.com/golang/go
synced 2024-11-08 04:26:09 -07:00
cmd/compile: refactor out an almost-superfluous arg
Moved all "target" information into "storeRC"; it was a register cursor, now it is a register cursor that also carries the store target with it if there are no registers. Also allows booby-trapping to ensure that the target is unambiguously one or the other. For #40724. Change-Id: I53ba4b91679e5fcc89c63b7d31225135299c6ec6 Reviewed-on: https://go-review.googlesource.com/c/go/+/293397 Trust: David Chase <drchase@google.com> Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
775f11cda1
commit
04a4dca2ac
@ -62,12 +62,31 @@ func removeTrivialWrapperTypes(t *types.Type) *types.Type {
|
|||||||
// A registerCursor tracks which register is used for an Arg or regValues, or a piece of such.
|
// A registerCursor tracks which register is used for an Arg or regValues, or a piece of such.
|
||||||
type registerCursor struct {
|
type registerCursor struct {
|
||||||
// TODO(register args) convert this to a generalized target cursor.
|
// TODO(register args) convert this to a generalized target cursor.
|
||||||
|
storeDest *Value // if there are no register targets, then this is the base of the store.
|
||||||
regsLen int // the number of registers available for this Arg/result (which is all in registers or not at all)
|
regsLen int // the number of registers available for this Arg/result (which is all in registers or not at all)
|
||||||
nextSlice Abi1RO // the next register/register-slice offset
|
nextSlice Abi1RO // the next register/register-slice offset
|
||||||
config *abi.ABIConfig
|
config *abi.ABIConfig
|
||||||
regValues *[]*Value // values assigned to registers accumulate here
|
regValues *[]*Value // values assigned to registers accumulate here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rc *registerCursor) String() string {
|
||||||
|
dest := "<none>"
|
||||||
|
if rc.storeDest != nil {
|
||||||
|
dest = rc.storeDest.String()
|
||||||
|
}
|
||||||
|
regs := "<none>"
|
||||||
|
if rc.regValues != nil {
|
||||||
|
regs = ""
|
||||||
|
for i, x := range *rc.regValues {
|
||||||
|
if i > 0 {
|
||||||
|
regs = regs + "; "
|
||||||
|
}
|
||||||
|
regs = regs + x.LongString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("RCSR{storeDest=%v, regsLen=%d, nextSlice=%d, regValues=[%s], config=%v", dest, rc.regsLen, rc.nextSlice, regs, rc.config)
|
||||||
|
}
|
||||||
|
|
||||||
// next effectively post-increments the register cursor; the receiver is advanced,
|
// next effectively post-increments the register cursor; the receiver is advanced,
|
||||||
// the old value is returned.
|
// the old value is returned.
|
||||||
func (c *registerCursor) next(t *types.Type) registerCursor {
|
func (c *registerCursor) next(t *types.Type) registerCursor {
|
||||||
@ -139,10 +158,11 @@ func (c *registerCursor) at(t *types.Type, i int) registerCursor {
|
|||||||
panic("Haven't implemented this case yet, do I need to?")
|
panic("Haven't implemented this case yet, do I need to?")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *registerCursor) init(regs []abi.RegIndex, info *abi.ABIParamResultInfo, result *[]*Value) {
|
func (c *registerCursor) init(regs []abi.RegIndex, info *abi.ABIParamResultInfo, result *[]*Value, storeDest *Value) {
|
||||||
c.regsLen = len(regs)
|
c.regsLen = len(regs)
|
||||||
c.nextSlice = 0
|
c.nextSlice = 0
|
||||||
if len(regs) == 0 {
|
if len(regs) == 0 {
|
||||||
|
c.storeDest = storeDest // only save this if there are no registers, will explode if misused.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.config = info.Config()
|
c.config = info.Config()
|
||||||
@ -519,20 +539,20 @@ func (x *expandState) rewriteDereference(b *Block, base, a, mem *Value, offset,
|
|||||||
// Parameters:
|
// Parameters:
|
||||||
// pos -- the location of any generated code.
|
// pos -- the location of any generated code.
|
||||||
// b -- the block into which any generated code should normally be placed
|
// b -- the block into which any generated code should normally be placed
|
||||||
// base -- for the stores that will ultimately be generated, the base to which the offset is applied. (Note this disappears in a future CL, folded into storeRc)
|
|
||||||
// source -- the value, possibly an aggregate, to be stored.
|
// source -- the value, possibly an aggregate, to be stored.
|
||||||
// mem -- the mem flowing into this decomposition (loads depend on it, stores updated it)
|
// mem -- the mem flowing into this decomposition (loads depend on it, stores updated it)
|
||||||
// t -- the type of the value to be stored
|
// t -- the type of the value to be stored
|
||||||
// offset -- if the value is stored in memory, it is stored at base + offset
|
// offset -- if the value is stored in memory, it is stored at base (see storeRc) + offset
|
||||||
// loadRegOffset -- regarding source as a value in registers, the register offset in ABI1. Meaningful only if source is OpArg.
|
// loadRegOffset -- regarding source as a value in registers, the register offset in ABI1. Meaningful only if source is OpArg.
|
||||||
// storeRc -- storeRC; if the value is stored in registers, this specifies the registers. StoreRc also identifies whether the target is registers or memory.
|
// storeRc -- storeRC; if the value is stored in registers, this specifies the registers.
|
||||||
|
// StoreRc also identifies whether the target is registers or memory, and has the base for the store operation.
|
||||||
//
|
//
|
||||||
// TODO -- this needs cleanup; it just works for SSA-able aggregates, and won't fully generalize to register-args aggregates.
|
// TODO -- this needs cleanup; it just works for SSA-able aggregates, and won't fully generalize to register-args aggregates.
|
||||||
func (x *expandState) decomposeArgOrLoad(pos src.XPos, b *Block, base, source, mem *Value, t *types.Type, offset int64, loadRegOffset Abi1RO, storeRc registerCursor,
|
func (x *expandState) decomposeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, t *types.Type, offset int64, loadRegOffset Abi1RO, storeRc registerCursor,
|
||||||
// For decompose One and Two, the additional offArg provides the offset from the beginning of "source", if it is in memory.
|
// For decompose One and Two, the additional offArg provides the offset from the beginning of "source", if it is in memory.
|
||||||
// offStore is combined to base to obtain a store destionation, like "offset" of decomposeArgOrLoad
|
// offStore is combined to base to obtain a store destionation, like "offset" of decomposeArgOrLoad
|
||||||
decomposeOne func(x *expandState, pos src.XPos, b *Block, base, source, mem *Value, t1 *types.Type, offArg, offStore int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value,
|
decomposeOne func(x *expandState, pos src.XPos, b *Block, source, mem *Value, t1 *types.Type, offArg, offStore int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value,
|
||||||
decomposeTwo func(x *expandState, pos src.XPos, b *Block, base, source, mem *Value, t1, t2 *types.Type, offArg, offStore int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value) *Value {
|
decomposeTwo func(x *expandState, pos src.XPos, b *Block, source, mem *Value, t1, t2 *types.Type, offArg, offStore int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value) *Value {
|
||||||
u := source.Type
|
u := source.Type
|
||||||
switch u.Kind() {
|
switch u.Kind() {
|
||||||
case types.TARRAY:
|
case types.TARRAY:
|
||||||
@ -540,7 +560,7 @@ func (x *expandState) decomposeArgOrLoad(pos src.XPos, b *Block, base, source, m
|
|||||||
elemRO := x.regWidth(elem)
|
elemRO := x.regWidth(elem)
|
||||||
for i := int64(0); i < u.NumElem(); i++ {
|
for i := int64(0); i < u.NumElem(); i++ {
|
||||||
elemOff := i * elem.Size()
|
elemOff := i * elem.Size()
|
||||||
mem = decomposeOne(x, pos, b, base, source, mem, elem, elemOff, offset+elemOff, loadRegOffset, storeRc.next(elem))
|
mem = decomposeOne(x, pos, b, source, mem, elem, elemOff, offset+elemOff, loadRegOffset, storeRc.next(elem))
|
||||||
loadRegOffset += elemRO
|
loadRegOffset += elemRO
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
}
|
}
|
||||||
@ -548,7 +568,7 @@ func (x *expandState) decomposeArgOrLoad(pos src.XPos, b *Block, base, source, m
|
|||||||
case types.TSTRUCT:
|
case types.TSTRUCT:
|
||||||
for i := 0; i < u.NumFields(); i++ {
|
for i := 0; i < u.NumFields(); i++ {
|
||||||
fld := u.Field(i)
|
fld := u.Field(i)
|
||||||
mem = decomposeOne(x, pos, b, base, source, mem, fld.Type, fld.Offset, offset+fld.Offset, loadRegOffset, storeRc.next(fld.Type))
|
mem = decomposeOne(x, pos, b, source, mem, fld.Type, fld.Offset, offset+fld.Offset, loadRegOffset, storeRc.next(fld.Type))
|
||||||
loadRegOffset += x.regWidth(fld.Type)
|
loadRegOffset += x.regWidth(fld.Type)
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
}
|
}
|
||||||
@ -558,80 +578,78 @@ func (x *expandState) decomposeArgOrLoad(pos src.XPos, b *Block, base, source, m
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
tHi, tLo := x.intPairTypes(t.Kind())
|
tHi, tLo := x.intPairTypes(t.Kind())
|
||||||
mem = decomposeOne(x, pos, b, base, source, mem, tHi, x.hiOffset, offset+x.hiOffset, loadRegOffset+x.hiRo, storeRc.plus(x.hiRo))
|
mem = decomposeOne(x, pos, b, source, mem, tHi, x.hiOffset, offset+x.hiOffset, loadRegOffset+x.hiRo, storeRc.plus(x.hiRo))
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
return decomposeOne(x, pos, b, base, source, mem, tLo, x.lowOffset, offset+x.lowOffset, loadRegOffset+x.loRo, storeRc.plus(x.loRo))
|
return decomposeOne(x, pos, b, source, mem, tLo, x.lowOffset, offset+x.lowOffset, loadRegOffset+x.loRo, storeRc.plus(x.loRo))
|
||||||
case types.TINTER:
|
case types.TINTER:
|
||||||
return decomposeTwo(x, pos, b, base, source, mem, x.typs.Uintptr, x.typs.BytePtr, 0, offset, loadRegOffset, storeRc)
|
return decomposeTwo(x, pos, b, source, mem, x.typs.Uintptr, x.typs.BytePtr, 0, offset, loadRegOffset, storeRc)
|
||||||
case types.TSTRING:
|
case types.TSTRING:
|
||||||
return decomposeTwo(x, pos, b, base, source, mem, x.typs.BytePtr, x.typs.Int, 0, offset, loadRegOffset, storeRc)
|
return decomposeTwo(x, pos, b, source, mem, x.typs.BytePtr, x.typs.Int, 0, offset, loadRegOffset, storeRc)
|
||||||
case types.TCOMPLEX64:
|
case types.TCOMPLEX64:
|
||||||
return decomposeTwo(x, pos, b, base, source, mem, x.typs.Float32, x.typs.Float32, 0, offset, loadRegOffset, storeRc)
|
return decomposeTwo(x, pos, b, source, mem, x.typs.Float32, x.typs.Float32, 0, offset, loadRegOffset, storeRc)
|
||||||
case types.TCOMPLEX128:
|
case types.TCOMPLEX128:
|
||||||
return decomposeTwo(x, pos, b, base, source, mem, x.typs.Float64, x.typs.Float64, 0, offset, loadRegOffset, storeRc)
|
return decomposeTwo(x, pos, b, source, mem, x.typs.Float64, x.typs.Float64, 0, offset, loadRegOffset, storeRc)
|
||||||
case types.TSLICE:
|
case types.TSLICE:
|
||||||
mem = decomposeOne(x, pos, b, base, source, mem, x.typs.BytePtr, 0, offset, loadRegOffset, storeRc.next(x.typs.BytePtr))
|
mem = decomposeOne(x, pos, b, source, mem, x.typs.BytePtr, 0, offset, loadRegOffset, storeRc.next(x.typs.BytePtr))
|
||||||
return decomposeTwo(x, pos, b, base, source, mem, x.typs.Int, x.typs.Int, x.ptrSize, offset+x.ptrSize, loadRegOffset+RO_slice_len, storeRc)
|
return decomposeTwo(x, pos, b, source, mem, x.typs.Int, x.typs.Int, x.ptrSize, offset+x.ptrSize, loadRegOffset+RO_slice_len, storeRc)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// storeOneArg creates a decomposed (one step) arg that is then stored.
|
// storeOneArg creates a decomposed (one step) arg that is then stored.
|
||||||
// pos and b locate the store instruction, base is the base of the store target, source is the "base" of the value input,
|
// pos and b locate the store instruction, source is the "base" of the value input,
|
||||||
// mem is the input mem, t is the type in question, and offArg and offStore are the offsets from the respective bases.
|
// mem is the input mem, t is the type in question, and offArg and offStore are the offsets from the respective bases.
|
||||||
func storeOneArg(x *expandState, pos src.XPos, b *Block, base, source, mem *Value, t *types.Type, offArg, offStore int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value {
|
func storeOneArg(x *expandState, pos src.XPos, b *Block, source, mem *Value, t *types.Type, offArg, offStore int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value {
|
||||||
w := x.commonArgs[selKey{source, offArg, t.Width, t}]
|
w := x.commonArgs[selKey{source, offArg, t.Width, t}]
|
||||||
if w == nil {
|
if w == nil {
|
||||||
// w = source.Block.NewValue0IA(source.Pos, OpArg, t, offArg, source.Aux)
|
|
||||||
w = x.newArgToMemOrRegs(source, w, offArg, loadRegOffset, t, pos)
|
w = x.newArgToMemOrRegs(source, w, offArg, loadRegOffset, t, pos)
|
||||||
// x.commonArgs[selKey{source, offArg, t.Width, t}] = w
|
|
||||||
}
|
}
|
||||||
return x.storeArgOrLoad(pos, b, base, w, mem, t, offStore, loadRegOffset, storeRc)
|
return x.storeArgOrLoad(pos, b, w, mem, t, offStore, loadRegOffset, storeRc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// storeOneLoad creates a decomposed (one step) load that is then stored.
|
// storeOneLoad creates a decomposed (one step) load that is then stored.
|
||||||
func storeOneLoad(x *expandState, pos src.XPos, b *Block, base, source, mem *Value, t *types.Type, offArg, offStore int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value {
|
func storeOneLoad(x *expandState, pos src.XPos, b *Block, source, mem *Value, t *types.Type, offArg, offStore int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value {
|
||||||
from := x.offsetFrom(source.Args[0], offArg, types.NewPtr(t))
|
from := x.offsetFrom(source.Args[0], offArg, types.NewPtr(t))
|
||||||
w := source.Block.NewValue2(source.Pos, OpLoad, t, from, mem)
|
w := source.Block.NewValue2(source.Pos, OpLoad, t, from, mem)
|
||||||
return x.storeArgOrLoad(pos, b, base, w, mem, t, offStore, loadRegOffset, storeRc)
|
return x.storeArgOrLoad(pos, b, w, mem, t, offStore, loadRegOffset, storeRc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func storeTwoArg(x *expandState, pos src.XPos, b *Block, base, source, mem *Value, t1, t2 *types.Type, offArg, offStore int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value {
|
func storeTwoArg(x *expandState, pos src.XPos, b *Block, source, mem *Value, t1, t2 *types.Type, offArg, offStore int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value {
|
||||||
mem = storeOneArg(x, pos, b, base, source, mem, t1, offArg, offStore, loadRegOffset, storeRc.next(t1))
|
mem = storeOneArg(x, pos, b, source, mem, t1, offArg, offStore, loadRegOffset, storeRc.next(t1))
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
t1Size := t1.Size()
|
t1Size := t1.Size()
|
||||||
return storeOneArg(x, pos, b, base, source, mem, t2, offArg+t1Size, offStore+t1Size, loadRegOffset+1, storeRc)
|
return storeOneArg(x, pos, b, source, mem, t2, offArg+t1Size, offStore+t1Size, loadRegOffset+1, storeRc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// storeTwoLoad creates a pair of decomposed (one step) loads that are then stored.
|
// storeTwoLoad creates a pair of decomposed (one step) loads that are then stored.
|
||||||
// the elements of the pair must not require any additional alignment.
|
// the elements of the pair must not require any additional alignment.
|
||||||
func storeTwoLoad(x *expandState, pos src.XPos, b *Block, base, source, mem *Value, t1, t2 *types.Type, offArg, offStore int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value {
|
func storeTwoLoad(x *expandState, pos src.XPos, b *Block, source, mem *Value, t1, t2 *types.Type, offArg, offStore int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value {
|
||||||
mem = storeOneLoad(x, pos, b, base, source, mem, t1, offArg, offStore, loadRegOffset, storeRc.next(t1))
|
mem = storeOneLoad(x, pos, b, source, mem, t1, offArg, offStore, loadRegOffset, storeRc.next(t1))
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
t1Size := t1.Size()
|
t1Size := t1.Size()
|
||||||
return storeOneLoad(x, pos, b, base, source, mem, t2, offArg+t1Size, offStore+t1Size, loadRegOffset+1, storeRc)
|
return storeOneLoad(x, pos, b, source, mem, t2, offArg+t1Size, offStore+t1Size, loadRegOffset+1, storeRc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// storeArgOrLoad converts stores of SSA-able potentially aggregatable arguments (passed to a call) into a series of primitive-typed
|
// storeArgOrLoad converts stores of SSA-able potentially aggregatable arguments (passed to a call) into a series of primitive-typed
|
||||||
// stores of non-aggregate types. It recursively walks up a chain of selectors until it reaches a Load or an Arg.
|
// stores of non-aggregate types. It recursively walks up a chain of selectors until it reaches a Load or an Arg.
|
||||||
// If it does not reach a Load or an Arg, nothing happens; this allows a little freedom in phase ordering.
|
// If it does not reach a Load or an Arg, nothing happens; this allows a little freedom in phase ordering.
|
||||||
func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, base, source, mem *Value, t *types.Type, offset int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value {
|
func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, t *types.Type, offset int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value {
|
||||||
if x.debug {
|
if x.debug {
|
||||||
fmt.Printf("\tstoreArgOrLoad(%s; %s; %s; %s; %d)\n", base.LongString(), source.LongString(), mem.String(), t.String(), offset)
|
fmt.Printf("\tstoreArgOrLoad(%s; %s; %s; %d; %s)\n", source.LongString(), mem.String(), t.String(), offset, storeRc.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
switch source.Op {
|
switch source.Op {
|
||||||
case OpCopy:
|
case OpCopy:
|
||||||
return x.storeArgOrLoad(pos, b, base, source.Args[0], mem, t, offset, loadRegOffset, storeRc)
|
return x.storeArgOrLoad(pos, b, source.Args[0], mem, t, offset, loadRegOffset, storeRc)
|
||||||
|
|
||||||
case OpLoad:
|
case OpLoad:
|
||||||
ret := x.decomposeArgOrLoad(pos, b, base, source, mem, t, offset, loadRegOffset, storeRc, storeOneLoad, storeTwoLoad)
|
ret := x.decomposeArgOrLoad(pos, b, source, mem, t, offset, loadRegOffset, storeRc, storeOneLoad, storeTwoLoad)
|
||||||
if ret != nil {
|
if ret != nil {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpArg:
|
case OpArg:
|
||||||
ret := x.decomposeArgOrLoad(pos, b, base, source, mem, t, offset, loadRegOffset, storeRc, storeOneArg, storeTwoArg)
|
ret := x.decomposeArgOrLoad(pos, b, source, mem, t, offset, loadRegOffset, storeRc, storeOneArg, storeTwoArg)
|
||||||
if ret != nil {
|
if ret != nil {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
@ -643,19 +661,19 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, base, source, mem *
|
|||||||
case OpStructMake1, OpStructMake2, OpStructMake3, OpStructMake4:
|
case OpStructMake1, OpStructMake2, OpStructMake3, OpStructMake4:
|
||||||
for i := 0; i < t.NumFields(); i++ {
|
for i := 0; i < t.NumFields(); i++ {
|
||||||
fld := t.Field(i)
|
fld := t.Field(i)
|
||||||
mem = x.storeArgOrLoad(pos, b, base, source.Args[i], mem, fld.Type, offset+fld.Offset, 0, storeRc.next(fld.Type))
|
mem = x.storeArgOrLoad(pos, b, source.Args[i], mem, fld.Type, offset+fld.Offset, 0, storeRc.next(fld.Type))
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
}
|
}
|
||||||
return mem
|
return mem
|
||||||
|
|
||||||
case OpArrayMake1:
|
case OpArrayMake1:
|
||||||
return x.storeArgOrLoad(pos, b, base, source.Args[0], mem, t.Elem(), offset, 0, storeRc.at(t, 0))
|
return x.storeArgOrLoad(pos, b, source.Args[0], mem, t.Elem(), offset, 0, storeRc.at(t, 0))
|
||||||
|
|
||||||
case OpInt64Make:
|
case OpInt64Make:
|
||||||
tHi, tLo := x.intPairTypes(t.Kind())
|
tHi, tLo := x.intPairTypes(t.Kind())
|
||||||
mem = x.storeArgOrLoad(pos, b, base, source.Args[0], mem, tHi, offset+x.hiOffset, 0, storeRc.next(tHi))
|
mem = x.storeArgOrLoad(pos, b, source.Args[0], mem, tHi, offset+x.hiOffset, 0, storeRc.next(tHi))
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
return x.storeArgOrLoad(pos, b, base, source.Args[1], mem, tLo, offset+x.lowOffset, 0, storeRc)
|
return x.storeArgOrLoad(pos, b, source.Args[1], mem, tLo, offset+x.lowOffset, 0, storeRc)
|
||||||
|
|
||||||
case OpComplexMake:
|
case OpComplexMake:
|
||||||
tPart := x.typs.Float32
|
tPart := x.typs.Float32
|
||||||
@ -663,25 +681,25 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, base, source, mem *
|
|||||||
if wPart == 8 {
|
if wPart == 8 {
|
||||||
tPart = x.typs.Float64
|
tPart = x.typs.Float64
|
||||||
}
|
}
|
||||||
mem = x.storeArgOrLoad(pos, b, base, source.Args[0], mem, tPart, offset, 0, storeRc.next(tPart))
|
mem = x.storeArgOrLoad(pos, b, source.Args[0], mem, tPart, offset, 0, storeRc.next(tPart))
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
return x.storeArgOrLoad(pos, b, base, source.Args[1], mem, tPart, offset+wPart, 0, storeRc)
|
return x.storeArgOrLoad(pos, b, source.Args[1], mem, tPart, offset+wPart, 0, storeRc)
|
||||||
|
|
||||||
case OpIMake:
|
case OpIMake:
|
||||||
mem = x.storeArgOrLoad(pos, b, base, source.Args[0], mem, x.typs.Uintptr, offset, 0, storeRc.next(x.typs.Uintptr))
|
mem = x.storeArgOrLoad(pos, b, source.Args[0], mem, x.typs.Uintptr, offset, 0, storeRc.next(x.typs.Uintptr))
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
return x.storeArgOrLoad(pos, b, base, source.Args[1], mem, x.typs.BytePtr, offset+x.ptrSize, 0, storeRc)
|
return x.storeArgOrLoad(pos, b, source.Args[1], mem, x.typs.BytePtr, offset+x.ptrSize, 0, storeRc)
|
||||||
|
|
||||||
case OpStringMake:
|
case OpStringMake:
|
||||||
mem = x.storeArgOrLoad(pos, b, base, source.Args[0], mem, x.typs.BytePtr, offset, 0, storeRc.next(x.typs.BytePtr))
|
mem = x.storeArgOrLoad(pos, b, source.Args[0], mem, x.typs.BytePtr, offset, 0, storeRc.next(x.typs.BytePtr))
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
return x.storeArgOrLoad(pos, b, base, source.Args[1], mem, x.typs.Int, offset+x.ptrSize, 0, storeRc)
|
return x.storeArgOrLoad(pos, b, source.Args[1], mem, x.typs.Int, offset+x.ptrSize, 0, storeRc)
|
||||||
|
|
||||||
case OpSliceMake:
|
case OpSliceMake:
|
||||||
mem = x.storeArgOrLoad(pos, b, base, source.Args[0], mem, x.typs.BytePtr, offset, 0, storeRc.next(x.typs.BytePtr))
|
mem = x.storeArgOrLoad(pos, b, source.Args[0], mem, x.typs.BytePtr, offset, 0, storeRc.next(x.typs.BytePtr))
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
mem = x.storeArgOrLoad(pos, b, base, source.Args[1], mem, x.typs.Int, offset+x.ptrSize, 0, storeRc.next(x.typs.Int))
|
mem = x.storeArgOrLoad(pos, b, source.Args[1], mem, x.typs.Int, offset+x.ptrSize, 0, storeRc.next(x.typs.Int))
|
||||||
return x.storeArgOrLoad(pos, b, base, source.Args[2], mem, x.typs.Int, offset+2*x.ptrSize, 0, storeRc)
|
return x.storeArgOrLoad(pos, b, source.Args[2], mem, x.typs.Int, offset+2*x.ptrSize, 0, storeRc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// For nodes that cannot be taken apart -- OpSelectN, other structure selectors.
|
// For nodes that cannot be taken apart -- OpSelectN, other structure selectors.
|
||||||
@ -691,12 +709,12 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, base, source, mem *
|
|||||||
if source.Type != t && t.NumElem() == 1 && elt.Width == t.Width && t.Width == x.regSize {
|
if source.Type != t && t.NumElem() == 1 && elt.Width == t.Width && t.Width == x.regSize {
|
||||||
t = removeTrivialWrapperTypes(t)
|
t = removeTrivialWrapperTypes(t)
|
||||||
// it could be a leaf type, but the "leaf" could be complex64 (for example)
|
// it could be a leaf type, but the "leaf" could be complex64 (for example)
|
||||||
return x.storeArgOrLoad(pos, b, base, source, mem, t, offset, loadRegOffset, storeRc)
|
return x.storeArgOrLoad(pos, b, source, mem, t, offset, loadRegOffset, storeRc)
|
||||||
}
|
}
|
||||||
eltRO := x.regWidth(elt)
|
eltRO := x.regWidth(elt)
|
||||||
for i := int64(0); i < t.NumElem(); i++ {
|
for i := int64(0); i < t.NumElem(); i++ {
|
||||||
sel := source.Block.NewValue1I(pos, OpArraySelect, elt, i, source)
|
sel := source.Block.NewValue1I(pos, OpArraySelect, elt, i, source)
|
||||||
mem = x.storeArgOrLoad(pos, b, base, sel, mem, elt, offset+i*elt.Width, loadRegOffset, storeRc.at(t, 0))
|
mem = x.storeArgOrLoad(pos, b, sel, mem, elt, offset+i*elt.Width, loadRegOffset, storeRc.at(t, 0))
|
||||||
loadRegOffset += eltRO
|
loadRegOffset += eltRO
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
}
|
}
|
||||||
@ -724,13 +742,13 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, base, source, mem *
|
|||||||
// of a *uint8, which does not succeed.
|
// of a *uint8, which does not succeed.
|
||||||
t = removeTrivialWrapperTypes(t)
|
t = removeTrivialWrapperTypes(t)
|
||||||
// it could be a leaf type, but the "leaf" could be complex64 (for example)
|
// it could be a leaf type, but the "leaf" could be complex64 (for example)
|
||||||
return x.storeArgOrLoad(pos, b, base, source, mem, t, offset, loadRegOffset, storeRc)
|
return x.storeArgOrLoad(pos, b, source, mem, t, offset, loadRegOffset, storeRc)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < t.NumFields(); i++ {
|
for i := 0; i < t.NumFields(); i++ {
|
||||||
fld := t.Field(i)
|
fld := t.Field(i)
|
||||||
sel := source.Block.NewValue1I(pos, OpStructSelect, fld.Type, int64(i), source)
|
sel := source.Block.NewValue1I(pos, OpStructSelect, fld.Type, int64(i), source)
|
||||||
mem = x.storeArgOrLoad(pos, b, base, sel, mem, fld.Type, offset+fld.Offset, loadRegOffset, storeRc.next(fld.Type))
|
mem = x.storeArgOrLoad(pos, b, sel, mem, fld.Type, offset+fld.Offset, loadRegOffset, storeRc.next(fld.Type))
|
||||||
loadRegOffset += x.regWidth(fld.Type)
|
loadRegOffset += x.regWidth(fld.Type)
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
}
|
}
|
||||||
@ -742,48 +760,48 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, base, source, mem *
|
|||||||
}
|
}
|
||||||
tHi, tLo := x.intPairTypes(t.Kind())
|
tHi, tLo := x.intPairTypes(t.Kind())
|
||||||
sel := source.Block.NewValue1(pos, OpInt64Hi, tHi, source)
|
sel := source.Block.NewValue1(pos, OpInt64Hi, tHi, source)
|
||||||
mem = x.storeArgOrLoad(pos, b, base, sel, mem, tHi, offset+x.hiOffset, loadRegOffset+x.hiRo, storeRc.plus(x.hiRo))
|
mem = x.storeArgOrLoad(pos, b, sel, mem, tHi, offset+x.hiOffset, loadRegOffset+x.hiRo, storeRc.plus(x.hiRo))
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
sel = source.Block.NewValue1(pos, OpInt64Lo, tLo, source)
|
sel = source.Block.NewValue1(pos, OpInt64Lo, tLo, source)
|
||||||
return x.storeArgOrLoad(pos, b, base, sel, mem, tLo, offset+x.lowOffset, loadRegOffset+x.loRo, storeRc.plus(x.hiRo))
|
return x.storeArgOrLoad(pos, b, sel, mem, tLo, offset+x.lowOffset, loadRegOffset+x.loRo, storeRc.plus(x.hiRo))
|
||||||
|
|
||||||
case types.TINTER:
|
case types.TINTER:
|
||||||
sel := source.Block.NewValue1(pos, OpITab, x.typs.BytePtr, source)
|
sel := source.Block.NewValue1(pos, OpITab, x.typs.BytePtr, source)
|
||||||
mem = x.storeArgOrLoad(pos, b, base, sel, mem, x.typs.BytePtr, offset, loadRegOffset, storeRc.next(x.typs.BytePtr))
|
mem = x.storeArgOrLoad(pos, b, sel, mem, x.typs.BytePtr, offset, loadRegOffset, storeRc.next(x.typs.BytePtr))
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
sel = source.Block.NewValue1(pos, OpIData, x.typs.BytePtr, source)
|
sel = source.Block.NewValue1(pos, OpIData, x.typs.BytePtr, source)
|
||||||
return x.storeArgOrLoad(pos, b, base, sel, mem, x.typs.BytePtr, offset+x.ptrSize, loadRegOffset+RO_iface_data, storeRc)
|
return x.storeArgOrLoad(pos, b, sel, mem, x.typs.BytePtr, offset+x.ptrSize, loadRegOffset+RO_iface_data, storeRc)
|
||||||
|
|
||||||
case types.TSTRING:
|
case types.TSTRING:
|
||||||
sel := source.Block.NewValue1(pos, OpStringPtr, x.typs.BytePtr, source)
|
sel := source.Block.NewValue1(pos, OpStringPtr, x.typs.BytePtr, source)
|
||||||
mem = x.storeArgOrLoad(pos, b, base, sel, mem, x.typs.BytePtr, offset, loadRegOffset, storeRc.next(x.typs.BytePtr))
|
mem = x.storeArgOrLoad(pos, b, sel, mem, x.typs.BytePtr, offset, loadRegOffset, storeRc.next(x.typs.BytePtr))
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
sel = source.Block.NewValue1(pos, OpStringLen, x.typs.Int, source)
|
sel = source.Block.NewValue1(pos, OpStringLen, x.typs.Int, source)
|
||||||
return x.storeArgOrLoad(pos, b, base, sel, mem, x.typs.Int, offset+x.ptrSize, loadRegOffset+RO_string_len, storeRc)
|
return x.storeArgOrLoad(pos, b, sel, mem, x.typs.Int, offset+x.ptrSize, loadRegOffset+RO_string_len, storeRc)
|
||||||
|
|
||||||
case types.TSLICE:
|
case types.TSLICE:
|
||||||
et := types.NewPtr(t.Elem())
|
et := types.NewPtr(t.Elem())
|
||||||
sel := source.Block.NewValue1(pos, OpSlicePtr, et, source)
|
sel := source.Block.NewValue1(pos, OpSlicePtr, et, source)
|
||||||
mem = x.storeArgOrLoad(pos, b, base, sel, mem, et, offset, loadRegOffset, storeRc.next(et))
|
mem = x.storeArgOrLoad(pos, b, sel, mem, et, offset, loadRegOffset, storeRc.next(et))
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
sel = source.Block.NewValue1(pos, OpSliceLen, x.typs.Int, source)
|
sel = source.Block.NewValue1(pos, OpSliceLen, x.typs.Int, source)
|
||||||
mem = x.storeArgOrLoad(pos, b, base, sel, mem, x.typs.Int, offset+x.ptrSize, loadRegOffset+RO_slice_len, storeRc.next(x.typs.Int))
|
mem = x.storeArgOrLoad(pos, b, sel, mem, x.typs.Int, offset+x.ptrSize, loadRegOffset+RO_slice_len, storeRc.next(x.typs.Int))
|
||||||
sel = source.Block.NewValue1(pos, OpSliceCap, x.typs.Int, source)
|
sel = source.Block.NewValue1(pos, OpSliceCap, x.typs.Int, source)
|
||||||
return x.storeArgOrLoad(pos, b, base, sel, mem, x.typs.Int, offset+2*x.ptrSize, loadRegOffset+RO_slice_cap, storeRc)
|
return x.storeArgOrLoad(pos, b, sel, mem, x.typs.Int, offset+2*x.ptrSize, loadRegOffset+RO_slice_cap, storeRc)
|
||||||
|
|
||||||
case types.TCOMPLEX64:
|
case types.TCOMPLEX64:
|
||||||
sel := source.Block.NewValue1(pos, OpComplexReal, x.typs.Float32, source)
|
sel := source.Block.NewValue1(pos, OpComplexReal, x.typs.Float32, source)
|
||||||
mem = x.storeArgOrLoad(pos, b, base, sel, mem, x.typs.Float32, offset, loadRegOffset, storeRc.next(x.typs.Float32))
|
mem = x.storeArgOrLoad(pos, b, sel, mem, x.typs.Float32, offset, loadRegOffset, storeRc.next(x.typs.Float32))
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
sel = source.Block.NewValue1(pos, OpComplexImag, x.typs.Float32, source)
|
sel = source.Block.NewValue1(pos, OpComplexImag, x.typs.Float32, source)
|
||||||
return x.storeArgOrLoad(pos, b, base, sel, mem, x.typs.Float32, offset+4, loadRegOffset+RO_complex_imag, storeRc)
|
return x.storeArgOrLoad(pos, b, sel, mem, x.typs.Float32, offset+4, loadRegOffset+RO_complex_imag, storeRc)
|
||||||
|
|
||||||
case types.TCOMPLEX128:
|
case types.TCOMPLEX128:
|
||||||
sel := source.Block.NewValue1(pos, OpComplexReal, x.typs.Float64, source)
|
sel := source.Block.NewValue1(pos, OpComplexReal, x.typs.Float64, source)
|
||||||
mem = x.storeArgOrLoad(pos, b, base, sel, mem, x.typs.Float64, offset, loadRegOffset, storeRc.next(x.typs.Float64))
|
mem = x.storeArgOrLoad(pos, b, sel, mem, x.typs.Float64, offset, loadRegOffset, storeRc.next(x.typs.Float64))
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
sel = source.Block.NewValue1(pos, OpComplexImag, x.typs.Float64, source)
|
sel = source.Block.NewValue1(pos, OpComplexImag, x.typs.Float64, source)
|
||||||
return x.storeArgOrLoad(pos, b, base, sel, mem, x.typs.Float64, offset+8, loadRegOffset+RO_complex_imag, storeRc)
|
return x.storeArgOrLoad(pos, b, sel, mem, x.typs.Float64, offset+8, loadRegOffset+RO_complex_imag, storeRc)
|
||||||
}
|
}
|
||||||
|
|
||||||
s := mem
|
s := mem
|
||||||
@ -791,7 +809,7 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, base, source, mem *
|
|||||||
// TODO(register args)
|
// TODO(register args)
|
||||||
storeRc.addArg(source)
|
storeRc.addArg(source)
|
||||||
} else {
|
} else {
|
||||||
dst := x.offsetFrom(base, offset, types.NewPtr(t))
|
dst := x.offsetFrom(storeRc.storeDest, offset, types.NewPtr(t))
|
||||||
s = b.NewValue3A(pos, OpStore, types.TypeMem, t, dst, source, mem)
|
s = b.NewValue3A(pos, OpStore, types.TypeMem, t, dst, source, mem)
|
||||||
}
|
}
|
||||||
if x.debug {
|
if x.debug {
|
||||||
@ -843,8 +861,8 @@ func (x *expandState) rewriteArgs(v *Value, firstArg int) *Value {
|
|||||||
if x.debug {
|
if x.debug {
|
||||||
fmt.Printf("storeArg %s, %v, %d\n", a.LongString(), aType, aOffset)
|
fmt.Printf("storeArg %s, %v, %d\n", a.LongString(), aType, aOffset)
|
||||||
}
|
}
|
||||||
rc.init(aRegs, aux.abiInfo, result)
|
rc.init(aRegs, aux.abiInfo, result, x.sp)
|
||||||
mem = x.storeArgOrLoad(pos, v.Block, x.sp, a, mem, aType, aOffset, 0, rc)
|
mem = x.storeArgOrLoad(pos, v.Block, a, mem, aType, aOffset, 0, rc)
|
||||||
// TODO append mem to Result, update type
|
// TODO append mem to Result, update type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -959,9 +977,9 @@ func expandCalls(f *Func) {
|
|||||||
if len(aRegs) > 0 {
|
if len(aRegs) > 0 {
|
||||||
result = &allResults
|
result = &allResults
|
||||||
}
|
}
|
||||||
rc.init(aRegs, aux.abiInfo, result)
|
rc.init(aRegs, aux.abiInfo, result, auxBase)
|
||||||
// TODO(register args)
|
// TODO REGISTER
|
||||||
mem = x.storeArgOrLoad(v.Pos, b, auxBase, a, mem, aux.TypeOfResult(i), auxOffset, 0, rc)
|
mem = x.storeArgOrLoad(v.Pos, b, a, mem, aux.TypeOfResult(i), auxOffset, 0, rc)
|
||||||
// TODO append mem to Result, update type
|
// TODO append mem to Result, update type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1005,7 +1023,7 @@ func expandCalls(f *Func) {
|
|||||||
fmt.Printf("Splitting store %s\n", v.LongString())
|
fmt.Printf("Splitting store %s\n", v.LongString())
|
||||||
}
|
}
|
||||||
dst, mem := v.Args[0], v.Args[2]
|
dst, mem := v.Args[0], v.Args[2]
|
||||||
mem = x.storeArgOrLoad(v.Pos, b, dst, source, mem, t, 0, 0, registerCursor{})
|
mem = x.storeArgOrLoad(v.Pos, b, source, mem, t, 0, 0, registerCursor{storeDest: dst})
|
||||||
v.copyOf(mem)
|
v.copyOf(mem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user