mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
reflect: refactor funcLayout tests
This change refactors the existing funcLayout tests and sets them up to support the new register ABI by explicitly setting the register counts to zero. This allows the test to pass if GOEXPERIMENT=regabiargs is set. A follow-up change will add tests for a non-zero register count. For #40724. Change-Id: Ibbe061b4ed4fd70566eb38b9e6182dca32b81127 Reviewed-on: https://go-review.googlesource.com/c/go/+/307869 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
0a510478b0
commit
b084073b53
3 changed files with 157 additions and 187 deletions
|
|
@ -6396,144 +6396,135 @@ func clobber() {
|
|||
runtime.GC()
|
||||
}
|
||||
|
||||
type funcLayoutTest struct {
|
||||
rcvr, t Type
|
||||
size, argsize, retOffset uintptr
|
||||
stack []byte // pointer bitmap: 1 is pointer, 0 is scalar
|
||||
gc []byte
|
||||
}
|
||||
|
||||
var funcLayoutTests []funcLayoutTest
|
||||
|
||||
func init() {
|
||||
var argAlign uintptr = PtrSize
|
||||
roundup := func(x uintptr, a uintptr) uintptr {
|
||||
return (x + a - 1) / a * a
|
||||
func TestFuncLayout(t *testing.T) {
|
||||
align := func(x uintptr) uintptr {
|
||||
return (x + PtrSize - 1) &^ (PtrSize - 1)
|
||||
}
|
||||
|
||||
funcLayoutTests = append(funcLayoutTests,
|
||||
funcLayoutTest{
|
||||
nil,
|
||||
ValueOf(func(a, b string) string { return "" }).Type(),
|
||||
6 * PtrSize,
|
||||
4 * PtrSize,
|
||||
4 * PtrSize,
|
||||
[]byte{1, 0, 1, 0, 1},
|
||||
[]byte{1, 0, 1, 0, 1},
|
||||
})
|
||||
|
||||
var r []byte
|
||||
if PtrSize == 4 {
|
||||
r = []byte{0, 0, 0, 1}
|
||||
} else {
|
||||
r = []byte{0, 0, 1}
|
||||
}
|
||||
funcLayoutTests = append(funcLayoutTests,
|
||||
funcLayoutTest{
|
||||
nil,
|
||||
ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(),
|
||||
roundup(roundup(3*4, PtrSize)+PtrSize+2, argAlign),
|
||||
roundup(3*4, PtrSize) + PtrSize + 2,
|
||||
roundup(roundup(3*4, PtrSize)+PtrSize+2, argAlign),
|
||||
r,
|
||||
r,
|
||||
})
|
||||
|
||||
funcLayoutTests = append(funcLayoutTests,
|
||||
funcLayoutTest{
|
||||
nil,
|
||||
ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(),
|
||||
4 * PtrSize,
|
||||
4 * PtrSize,
|
||||
4 * PtrSize,
|
||||
[]byte{1, 0, 1, 1},
|
||||
[]byte{1, 0, 1, 1},
|
||||
})
|
||||
|
||||
type S struct {
|
||||
a, b uintptr
|
||||
c, d *byte
|
||||
}
|
||||
funcLayoutTests = append(funcLayoutTests,
|
||||
funcLayoutTest{
|
||||
nil,
|
||||
ValueOf(func(a S) {}).Type(),
|
||||
4 * PtrSize,
|
||||
4 * PtrSize,
|
||||
4 * PtrSize,
|
||||
[]byte{0, 0, 1, 1},
|
||||
[]byte{0, 0, 1, 1},
|
||||
})
|
||||
|
||||
funcLayoutTests = append(funcLayoutTests,
|
||||
funcLayoutTest{
|
||||
ValueOf((*byte)(nil)).Type(),
|
||||
ValueOf(func(a uintptr, b *int) {}).Type(),
|
||||
roundup(3*PtrSize, argAlign),
|
||||
3 * PtrSize,
|
||||
roundup(3*PtrSize, argAlign),
|
||||
[]byte{1, 0, 1},
|
||||
[]byte{1, 0, 1},
|
||||
})
|
||||
|
||||
funcLayoutTests = append(funcLayoutTests,
|
||||
funcLayoutTest{
|
||||
nil,
|
||||
ValueOf(func(a uintptr) {}).Type(),
|
||||
roundup(PtrSize, argAlign),
|
||||
PtrSize,
|
||||
roundup(PtrSize, argAlign),
|
||||
[]byte{},
|
||||
[]byte{},
|
||||
})
|
||||
|
||||
funcLayoutTests = append(funcLayoutTests,
|
||||
funcLayoutTest{
|
||||
nil,
|
||||
ValueOf(func() uintptr { return 0 }).Type(),
|
||||
PtrSize,
|
||||
0,
|
||||
0,
|
||||
[]byte{},
|
||||
[]byte{},
|
||||
})
|
||||
|
||||
funcLayoutTests = append(funcLayoutTests,
|
||||
funcLayoutTest{
|
||||
ValueOf(uintptr(0)).Type(),
|
||||
ValueOf(func(a uintptr) {}).Type(),
|
||||
2 * PtrSize,
|
||||
2 * PtrSize,
|
||||
2 * PtrSize,
|
||||
[]byte{1},
|
||||
[]byte{1},
|
||||
type test struct {
|
||||
rcvr, typ Type
|
||||
size, argsize, retOffset uintptr
|
||||
stack, gc, inRegs, outRegs []byte // pointer bitmap: 1 is pointer, 0 is scalar
|
||||
intRegs, floatRegs int
|
||||
floatRegSize uintptr
|
||||
}
|
||||
tests := []test{
|
||||
{
|
||||
typ: ValueOf(func(a, b string) string { return "" }).Type(),
|
||||
size: 6 * PtrSize,
|
||||
argsize: 4 * PtrSize,
|
||||
retOffset: 4 * PtrSize,
|
||||
stack: []byte{1, 0, 1, 0, 1},
|
||||
gc: []byte{1, 0, 1, 0, 1},
|
||||
},
|
||||
{
|
||||
typ: ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(),
|
||||
size: align(align(3*4) + PtrSize + 2),
|
||||
argsize: align(3*4) + PtrSize + 2,
|
||||
retOffset: align(align(3*4) + PtrSize + 2),
|
||||
stack: r,
|
||||
gc: r,
|
||||
},
|
||||
{
|
||||
typ: ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(),
|
||||
size: 4 * PtrSize,
|
||||
argsize: 4 * PtrSize,
|
||||
retOffset: 4 * PtrSize,
|
||||
stack: []byte{1, 0, 1, 1},
|
||||
gc: []byte{1, 0, 1, 1},
|
||||
},
|
||||
{
|
||||
typ: ValueOf(func(a S) {}).Type(),
|
||||
size: 4 * PtrSize,
|
||||
argsize: 4 * PtrSize,
|
||||
retOffset: 4 * PtrSize,
|
||||
stack: []byte{0, 0, 1, 1},
|
||||
gc: []byte{0, 0, 1, 1},
|
||||
},
|
||||
{
|
||||
rcvr: ValueOf((*byte)(nil)).Type(),
|
||||
typ: ValueOf(func(a uintptr, b *int) {}).Type(),
|
||||
size: 3 * PtrSize,
|
||||
argsize: 3 * PtrSize,
|
||||
retOffset: 3 * PtrSize,
|
||||
stack: []byte{1, 0, 1},
|
||||
gc: []byte{1, 0, 1},
|
||||
},
|
||||
{
|
||||
typ: ValueOf(func(a uintptr) {}).Type(),
|
||||
size: PtrSize,
|
||||
argsize: PtrSize,
|
||||
retOffset: PtrSize,
|
||||
stack: []byte{},
|
||||
gc: []byte{},
|
||||
},
|
||||
{
|
||||
typ: ValueOf(func() uintptr { return 0 }).Type(),
|
||||
size: PtrSize,
|
||||
argsize: 0,
|
||||
retOffset: 0,
|
||||
stack: []byte{},
|
||||
gc: []byte{},
|
||||
},
|
||||
{
|
||||
rcvr: ValueOf(uintptr(0)).Type(),
|
||||
typ: ValueOf(func(a uintptr) {}).Type(),
|
||||
size: 2 * PtrSize,
|
||||
argsize: 2 * PtrSize,
|
||||
retOffset: 2 * PtrSize,
|
||||
stack: []byte{1},
|
||||
gc: []byte{1},
|
||||
// Note: this one is tricky, as the receiver is not a pointer. But we
|
||||
// pass the receiver by reference to the autogenerated pointer-receiver
|
||||
// version of the function.
|
||||
})
|
||||
}
|
||||
},
|
||||
// TODO(mknyszek): Add tests for non-zero register count.
|
||||
}
|
||||
for _, lt := range tests {
|
||||
name := lt.typ.String()
|
||||
if lt.rcvr != nil {
|
||||
name = lt.rcvr.String() + "." + name
|
||||
}
|
||||
t.Run(name, func(t *testing.T) {
|
||||
defer SetArgRegs(SetArgRegs(lt.intRegs, lt.floatRegs, lt.floatRegSize))
|
||||
|
||||
func TestFuncLayout(t *testing.T) {
|
||||
for _, lt := range funcLayoutTests {
|
||||
typ, argsize, retOffset, stack, gc, ptrs := FuncLayout(lt.t, lt.rcvr)
|
||||
if typ.Size() != lt.size {
|
||||
t.Errorf("funcLayout(%v, %v).size=%d, want %d", lt.t, lt.rcvr, typ.Size(), lt.size)
|
||||
}
|
||||
if argsize != lt.argsize {
|
||||
t.Errorf("funcLayout(%v, %v).argsize=%d, want %d", lt.t, lt.rcvr, argsize, lt.argsize)
|
||||
}
|
||||
if retOffset != lt.retOffset {
|
||||
t.Errorf("funcLayout(%v, %v).retOffset=%d, want %d", lt.t, lt.rcvr, retOffset, lt.retOffset)
|
||||
}
|
||||
if !bytes.Equal(stack, lt.stack) {
|
||||
t.Errorf("funcLayout(%v, %v).stack=%v, want %v", lt.t, lt.rcvr, stack, lt.stack)
|
||||
}
|
||||
if !bytes.Equal(gc, lt.gc) {
|
||||
t.Errorf("funcLayout(%v, %v).gc=%v, want %v", lt.t, lt.rcvr, gc, lt.gc)
|
||||
}
|
||||
if ptrs && len(stack) == 0 || !ptrs && len(stack) > 0 {
|
||||
t.Errorf("funcLayout(%v, %v) pointers flag=%v, want %v", lt.t, lt.rcvr, ptrs, !ptrs)
|
||||
}
|
||||
typ, argsize, retOffset, stack, gc, inRegs, outRegs, ptrs := FuncLayout(lt.typ, lt.rcvr)
|
||||
if typ.Size() != lt.size {
|
||||
t.Errorf("funcLayout(%v, %v).size=%d, want %d", lt.typ, lt.rcvr, typ.Size(), lt.size)
|
||||
}
|
||||
if argsize != lt.argsize {
|
||||
t.Errorf("funcLayout(%v, %v).argsize=%d, want %d", lt.typ, lt.rcvr, argsize, lt.argsize)
|
||||
}
|
||||
if retOffset != lt.retOffset {
|
||||
t.Errorf("funcLayout(%v, %v).retOffset=%d, want %d", lt.typ, lt.rcvr, retOffset, lt.retOffset)
|
||||
}
|
||||
if !bytes.Equal(stack, lt.stack) {
|
||||
t.Errorf("funcLayout(%v, %v).stack=%v, want %v", lt.typ, lt.rcvr, stack, lt.stack)
|
||||
}
|
||||
if !bytes.Equal(gc, lt.gc) {
|
||||
t.Errorf("funcLayout(%v, %v).gc=%v, want %v", lt.typ, lt.rcvr, gc, lt.gc)
|
||||
}
|
||||
if !bytes.Equal(inRegs, lt.inRegs) {
|
||||
t.Errorf("funcLayout(%v, %v).inRegs=%v, want %v", lt.typ, lt.rcvr, inRegs, lt.inRegs)
|
||||
}
|
||||
if !bytes.Equal(outRegs, lt.outRegs) {
|
||||
t.Errorf("funcLayout(%v, %v).outRegs=%v, want %v", lt.typ, lt.rcvr, outRegs, lt.outRegs)
|
||||
}
|
||||
if ptrs && len(stack) == 0 || !ptrs && len(stack) > 0 {
|
||||
t.Errorf("funcLayout(%v, %v) pointers flag=%v, want %v", lt.typ, lt.rcvr, ptrs, !ptrs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue