Skip to content

Commit 2b8026f

Browse files
dr2chasecagedmantis
authored andcommitted
[release-branch.go1.21] cmd/compile: in expandCalls, move all arg marshalling into call block
For aggregate-typed arguments passed to a call, expandCalls decomposed them into parts in the same block where the value was created. This is not necessarily the call block, and in the case where stores are involved, can change the memory leaving that block, and getting that right is problematic. Instead, do all the expanding in the same block as the call, which avoids the problems of (1) not being able to reorder loads/stores across a block boundary to conform to memory order and (2) (incorrectly, not) exposing the new memory to consumers in other blocks. Putting it all in the same block as the call allows reordering, and the call creates its own new memory (which is already dealt with correctly). Fixes #62057. Updates #61992. Change-Id: Icc7918f0d2dd3c480cc7f496cdcd78edeca7f297 Reviewed-on: https://go-review.googlesource.com/c/go/+/519276 Reviewed-by: Keith Randall <[email protected]> Run-TryBot: David Chase <[email protected]> Reviewed-by: Keith Randall <[email protected]> TryBot-Result: Gopher Robot <[email protected]> (cherry picked from commit e72ecc6) Reviewed-on: https://go-review.googlesource.com/c/go/+/520058
1 parent 7c97cc7 commit 2b8026f

File tree

2 files changed

+45
-16
lines changed

2 files changed

+45
-16
lines changed

src/cmd/compile/internal/ssa/expand_calls.go

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,7 @@ func storeOneArg(x *expandState, pos src.XPos, b *Block, locs []*LocalSlot, suff
855855
// storeOneLoad creates a decomposed (one step) load that is then stored.
856856
func storeOneLoad(x *expandState, pos src.XPos, b *Block, source, mem *Value, t *types.Type, offArg, offStore int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value {
857857
from := x.offsetFrom(source.Block, source.Args[0], offArg, types.NewPtr(t))
858-
w := source.Block.NewValue2(source.Pos, OpLoad, t, from, mem)
858+
w := b.NewValue2(source.Pos, OpLoad, t, from, mem)
859859
return x.storeArgOrLoad(pos, b, w, mem, t, offStore, loadRegOffset, storeRc)
860860
}
861861

@@ -962,7 +962,7 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value,
962962
eltRO := x.regWidth(elt)
963963
source.Type = t
964964
for i := int64(0); i < t.NumElem(); i++ {
965-
sel := source.Block.NewValue1I(pos, OpArraySelect, elt, i, source)
965+
sel := b.NewValue1I(pos, OpArraySelect, elt, i, source)
966966
mem = x.storeArgOrLoad(pos, b, sel, mem, elt, storeOffset+i*elt.Size(), loadRegOffset, storeRc.at(t, 0))
967967
loadRegOffset += eltRO
968968
pos = pos.WithNotStmt()
@@ -997,7 +997,7 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value,
997997
source.Type = t
998998
for i := 0; i < t.NumFields(); i++ {
999999
fld := t.Field(i)
1000-
sel := source.Block.NewValue1I(pos, OpStructSelect, fld.Type, int64(i), source)
1000+
sel := b.NewValue1I(pos, OpStructSelect, fld.Type, int64(i), source)
10011001
mem = x.storeArgOrLoad(pos, b, sel, mem, fld.Type, storeOffset+fld.Offset, loadRegOffset, storeRc.next(fld.Type))
10021002
loadRegOffset += x.regWidth(fld.Type)
10031003
pos = pos.WithNotStmt()
@@ -1009,48 +1009,48 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value,
10091009
break
10101010
}
10111011
tHi, tLo := x.intPairTypes(t.Kind())
1012-
sel := source.Block.NewValue1(pos, OpInt64Hi, tHi, source)
1012+
sel := b.NewValue1(pos, OpInt64Hi, tHi, source)
10131013
mem = x.storeArgOrLoad(pos, b, sel, mem, tHi, storeOffset+x.hiOffset, loadRegOffset+x.hiRo, storeRc.plus(x.hiRo))
10141014
pos = pos.WithNotStmt()
1015-
sel = source.Block.NewValue1(pos, OpInt64Lo, tLo, source)
1015+
sel = b.NewValue1(pos, OpInt64Lo, tLo, source)
10161016
return x.storeArgOrLoad(pos, b, sel, mem, tLo, storeOffset+x.lowOffset, loadRegOffset+x.loRo, storeRc.plus(x.hiRo))
10171017

10181018
case types.TINTER:
1019-
sel := source.Block.NewValue1(pos, OpITab, x.typs.BytePtr, source)
1019+
sel := b.NewValue1(pos, OpITab, x.typs.BytePtr, source)
10201020
mem = x.storeArgOrLoad(pos, b, sel, mem, x.typs.BytePtr, storeOffset, loadRegOffset, storeRc.next(x.typs.BytePtr))
10211021
pos = pos.WithNotStmt()
1022-
sel = source.Block.NewValue1(pos, OpIData, x.typs.BytePtr, source)
1022+
sel = b.NewValue1(pos, OpIData, x.typs.BytePtr, source)
10231023
return x.storeArgOrLoad(pos, b, sel, mem, x.typs.BytePtr, storeOffset+x.ptrSize, loadRegOffset+RO_iface_data, storeRc)
10241024

10251025
case types.TSTRING:
1026-
sel := source.Block.NewValue1(pos, OpStringPtr, x.typs.BytePtr, source)
1026+
sel := b.NewValue1(pos, OpStringPtr, x.typs.BytePtr, source)
10271027
mem = x.storeArgOrLoad(pos, b, sel, mem, x.typs.BytePtr, storeOffset, loadRegOffset, storeRc.next(x.typs.BytePtr))
10281028
pos = pos.WithNotStmt()
1029-
sel = source.Block.NewValue1(pos, OpStringLen, x.typs.Int, source)
1029+
sel = b.NewValue1(pos, OpStringLen, x.typs.Int, source)
10301030
return x.storeArgOrLoad(pos, b, sel, mem, x.typs.Int, storeOffset+x.ptrSize, loadRegOffset+RO_string_len, storeRc)
10311031

10321032
case types.TSLICE:
10331033
et := types.NewPtr(t.Elem())
1034-
sel := source.Block.NewValue1(pos, OpSlicePtr, et, source)
1034+
sel := b.NewValue1(pos, OpSlicePtr, et, source)
10351035
mem = x.storeArgOrLoad(pos, b, sel, mem, et, storeOffset, loadRegOffset, storeRc.next(et))
10361036
pos = pos.WithNotStmt()
1037-
sel = source.Block.NewValue1(pos, OpSliceLen, x.typs.Int, source)
1037+
sel = b.NewValue1(pos, OpSliceLen, x.typs.Int, source)
10381038
mem = x.storeArgOrLoad(pos, b, sel, mem, x.typs.Int, storeOffset+x.ptrSize, loadRegOffset+RO_slice_len, storeRc.next(x.typs.Int))
1039-
sel = source.Block.NewValue1(pos, OpSliceCap, x.typs.Int, source)
1039+
sel = b.NewValue1(pos, OpSliceCap, x.typs.Int, source)
10401040
return x.storeArgOrLoad(pos, b, sel, mem, x.typs.Int, storeOffset+2*x.ptrSize, loadRegOffset+RO_slice_cap, storeRc)
10411041

10421042
case types.TCOMPLEX64:
1043-
sel := source.Block.NewValue1(pos, OpComplexReal, x.typs.Float32, source)
1043+
sel := b.NewValue1(pos, OpComplexReal, x.typs.Float32, source)
10441044
mem = x.storeArgOrLoad(pos, b, sel, mem, x.typs.Float32, storeOffset, loadRegOffset, storeRc.next(x.typs.Float32))
10451045
pos = pos.WithNotStmt()
1046-
sel = source.Block.NewValue1(pos, OpComplexImag, x.typs.Float32, source)
1046+
sel = b.NewValue1(pos, OpComplexImag, x.typs.Float32, source)
10471047
return x.storeArgOrLoad(pos, b, sel, mem, x.typs.Float32, storeOffset+4, loadRegOffset+RO_complex_imag, storeRc)
10481048

10491049
case types.TCOMPLEX128:
1050-
sel := source.Block.NewValue1(pos, OpComplexReal, x.typs.Float64, source)
1050+
sel := b.NewValue1(pos, OpComplexReal, x.typs.Float64, source)
10511051
mem = x.storeArgOrLoad(pos, b, sel, mem, x.typs.Float64, storeOffset, loadRegOffset, storeRc.next(x.typs.Float64))
10521052
pos = pos.WithNotStmt()
1053-
sel = source.Block.NewValue1(pos, OpComplexImag, x.typs.Float64, source)
1053+
sel = b.NewValue1(pos, OpComplexImag, x.typs.Float64, source)
10541054
return x.storeArgOrLoad(pos, b, sel, mem, x.typs.Float64, storeOffset+8, loadRegOffset+RO_complex_imag, storeRc)
10551055
}
10561056

@@ -1113,6 +1113,9 @@ func (x *expandState) rewriteArgs(v *Value, firstArg int) {
11131113
}
11141114
}
11151115
}
1116+
if x.debug > 1 {
1117+
x.Printf("...storeArg %s, %v, %d\n", a.LongString(), aType, aOffset)
1118+
}
11161119
// "Dereference" of addressed (probably not-SSA-eligible) value becomes Move
11171120
// TODO(register args) this will be more complicated with registers in the picture.
11181121
mem = x.rewriteDereference(v.Block, sp, a, mem, aOffset, aux.SizeOfArg(auxI), aType, v.Pos)

test/fixedbugs/issue61992.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// compile
2+
3+
// Copyright 2023 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
// Issue 61992, inconsistent 'mem' juggling in expandCalls
8+
9+
package p
10+
11+
type S1 struct {
12+
a, b, c []int
13+
i int
14+
}
15+
16+
type S2 struct {
17+
a, b []int
18+
m map[int]int
19+
}
20+
21+
func F(i int, f func(S1, S2, int) int) int {
22+
return f(
23+
S1{},
24+
S2{m: map[int]int{}},
25+
1<<i)
26+
}

0 commit comments

Comments
 (0)