diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index 87b8a02b25..1868e3f073 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -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. type registerCursor struct { // 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) nextSlice Abi1RO // the next register/register-slice offset config *abi.ABIConfig regValues *[]*Value // values assigned to registers accumulate here } +func (rc *registerCursor) String() string { + dest := "" + if rc.storeDest != nil { + dest = rc.storeDest.String() + } + regs := "" + 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, // the old value is returned. 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?") } -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.nextSlice = 0 if len(regs) == 0 { + c.storeDest = storeDest // only save this if there are no registers, will explode if misused. return } c.config = info.Config() @@ -519,20 +539,20 @@ func (x *expandState) rewriteDereference(b *Block, base, a, mem *Value, offset, // Parameters: // pos -- the location of any generated code. // 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. // mem -- the mem flowing into this decomposition (loads depend on it, stores updated it) // 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. -// 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. -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. // 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, - 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 { + 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, source, mem *Value, t1, t2 *types.Type, offArg, offStore int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value) *Value { u := source.Type switch u.Kind() { case types.TARRAY: @@ -540,7 +560,7 @@ func (x *expandState) decomposeArgOrLoad(pos src.XPos, b *Block, base, source, m elemRO := x.regWidth(elem) for i := int64(0); i < u.NumElem(); i++ { 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 pos = pos.WithNotStmt() } @@ -548,7 +568,7 @@ func (x *expandState) decomposeArgOrLoad(pos src.XPos, b *Block, base, source, m case types.TSTRUCT: for i := 0; i < u.NumFields(); 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) pos = pos.WithNotStmt() } @@ -558,80 +578,78 @@ func (x *expandState) decomposeArgOrLoad(pos src.XPos, b *Block, base, source, m break } 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() - 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: - 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: - 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: - 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: - 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: - mem = decomposeOne(x, pos, b, base, 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) + mem = decomposeOne(x, pos, b, source, mem, x.typs.BytePtr, 0, offset, loadRegOffset, storeRc.next(x.typs.BytePtr)) + 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 } // 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. -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}] if w == nil { - // w = source.Block.NewValue0IA(source.Pos, OpArg, t, offArg, source.Aux) 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. -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)) 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 { - mem = storeOneArg(x, pos, b, base, source, mem, t1, offArg, offStore, loadRegOffset, storeRc.next(t1)) +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, source, mem, t1, offArg, offStore, loadRegOffset, storeRc.next(t1)) pos = pos.WithNotStmt() 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. // 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 { - mem = storeOneLoad(x, pos, b, base, source, mem, t1, offArg, offStore, loadRegOffset, storeRc.next(t1)) +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, source, mem, t1, offArg, offStore, loadRegOffset, storeRc.next(t1)) pos = pos.WithNotStmt() 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 // 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. -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 { - 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 { 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: - 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 { return ret } 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 { return ret } @@ -643,19 +661,19 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, base, source, mem * case OpStructMake1, OpStructMake2, OpStructMake3, OpStructMake4: for i := 0; i < t.NumFields(); 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() } return mem 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: 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() - 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: tPart := x.typs.Float32 @@ -663,25 +681,25 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, base, source, mem * if wPart == 8 { 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() - 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: - 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() - 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: - 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() - 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: - 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() - mem = x.storeArgOrLoad(pos, b, base, 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) + 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, source.Args[2], mem, x.typs.Int, offset+2*x.ptrSize, 0, storeRc) } // 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 { t = removeTrivialWrapperTypes(t) // 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) for i := int64(0); i < t.NumElem(); i++ { 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 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. t = removeTrivialWrapperTypes(t) // 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++ { fld := t.Field(i) 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) 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()) 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() 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: 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() 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: 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() 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: et := types.NewPtr(t.Elem()) 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() 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) - 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: 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() 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: 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() 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 @@ -791,7 +809,7 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, base, source, mem * // TODO(register args) storeRc.addArg(source) } 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) } if x.debug { @@ -843,8 +861,8 @@ func (x *expandState) rewriteArgs(v *Value, firstArg int) *Value { if x.debug { fmt.Printf("storeArg %s, %v, %d\n", a.LongString(), aType, aOffset) } - rc.init(aRegs, aux.abiInfo, result) - mem = x.storeArgOrLoad(pos, v.Block, x.sp, a, mem, aType, aOffset, 0, rc) + rc.init(aRegs, aux.abiInfo, result, x.sp) + mem = x.storeArgOrLoad(pos, v.Block, a, mem, aType, aOffset, 0, rc) // TODO append mem to Result, update type } } @@ -959,9 +977,9 @@ func expandCalls(f *Func) { if len(aRegs) > 0 { result = &allResults } - rc.init(aRegs, aux.abiInfo, result) - // TODO(register args) - mem = x.storeArgOrLoad(v.Pos, b, auxBase, a, mem, aux.TypeOfResult(i), auxOffset, 0, rc) + rc.init(aRegs, aux.abiInfo, result, auxBase) + // TODO REGISTER + mem = x.storeArgOrLoad(v.Pos, b, a, mem, aux.TypeOfResult(i), auxOffset, 0, rc) // TODO append mem to Result, update type } } @@ -1005,7 +1023,7 @@ func expandCalls(f *Func) { fmt.Printf("Splitting store %s\n", v.LongString()) } 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) } }