1// Copyright 2021 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5//go:build goexperiment.regabiargs
6
7package reflect_test
8
9import (
10	"internal/abi"
11	"math"
12	"math/rand"
13	"reflect"
14	"runtime"
15	"testing"
16	"testing/quick"
17)
18
19// As of early May 2021 this is no longer necessary for amd64,
20// but it remains in case this is needed for the next register abi port.
21// TODO (1.18) If enabling register ABI on additional architectures turns out not to need this, remove it.
22type MagicLastTypeNameForTestingRegisterABI struct{}
23
24func TestMethodValueCallABI(t *testing.T) {
25	// Enable register-based reflect.Call and ensure we don't
26	// use potentially incorrect cached versions by clearing
27	// the cache before we start and after we're done.
28	defer reflect.SetArgRegs(reflect.SetArgRegs(abi.IntArgRegs, abi.FloatArgRegs, abi.EffectiveFloatRegSize))
29
30	// This test is simple. Calling a method value involves
31	// pretty much just plumbing whatever arguments in whichever
32	// location through to reflectcall. They're already set up
33	// for us, so there isn't a whole lot to do. Let's just
34	// make sure that we can pass register and stack arguments
35	// through. The exact combination is not super important.
36	makeMethodValue := func(method string) (*StructWithMethods, any) {
37		s := new(StructWithMethods)
38		v := reflect.ValueOf(s).MethodByName(method)
39		return s, v.Interface()
40	}
41
42	a0 := StructFewRegs{
43		10, 11, 12, 13,
44		20.0, 21.0, 22.0, 23.0,
45	}
46	a1 := [4]uint64{100, 101, 102, 103}
47	a2 := StructFillRegs{
48		1, 2, 3, 4, 5, 6, 7, 8, 9,
49		1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0,
50	}
51
52	s, i := makeMethodValue("AllRegsCall")
53	f0 := i.(func(StructFewRegs, MagicLastTypeNameForTestingRegisterABI) StructFewRegs)
54	r0 := f0(a0, MagicLastTypeNameForTestingRegisterABI{})
55	if r0 != a0 {
56		t.Errorf("bad method value call: got %#v, want %#v", r0, a0)
57	}
58	if s.Value != 1 {
59		t.Errorf("bad method value call: failed to set s.Value: got %d, want %d", s.Value, 1)
60	}
61
62	s, i = makeMethodValue("RegsAndStackCall")
63	f1 := i.(func(StructFewRegs, [4]uint64, MagicLastTypeNameForTestingRegisterABI) (StructFewRegs, [4]uint64))
64	r0, r1 := f1(a0, a1, MagicLastTypeNameForTestingRegisterABI{})
65	if r0 != a0 {
66		t.Errorf("bad method value call: got %#v, want %#v", r0, a0)
67	}
68	if r1 != a1 {
69		t.Errorf("bad method value call: got %#v, want %#v", r1, a1)
70	}
71	if s.Value != 2 {
72		t.Errorf("bad method value call: failed to set s.Value: got %d, want %d", s.Value, 2)
73	}
74
75	s, i = makeMethodValue("SpillStructCall")
76	f2 := i.(func(StructFillRegs, MagicLastTypeNameForTestingRegisterABI) StructFillRegs)
77	r2 := f2(a2, MagicLastTypeNameForTestingRegisterABI{})
78	if r2 != a2 {
79		t.Errorf("bad method value call: got %#v, want %#v", r2, a2)
80	}
81	if s.Value != 3 {
82		t.Errorf("bad method value call: failed to set s.Value: got %d, want %d", s.Value, 3)
83	}
84
85	s, i = makeMethodValue("ValueRegMethodSpillInt")
86	f3 := i.(func(StructFillRegs, int, MagicLastTypeNameForTestingRegisterABI) (StructFillRegs, int))
87	r3a, r3b := f3(a2, 42, MagicLastTypeNameForTestingRegisterABI{})
88	if r3a != a2 {
89		t.Errorf("bad method value call: got %#v, want %#v", r3a, a2)
90	}
91	if r3b != 42 {
92		t.Errorf("bad method value call: got %#v, want %#v", r3b, 42)
93	}
94	if s.Value != 4 {
95		t.Errorf("bad method value call: failed to set s.Value: got %d, want %d", s.Value, 4)
96	}
97
98	s, i = makeMethodValue("ValueRegMethodSpillPtr")
99	f4 := i.(func(StructFillRegs, *byte, MagicLastTypeNameForTestingRegisterABI) (StructFillRegs, *byte))
100	vb := byte(10)
101	r4a, r4b := f4(a2, &vb, MagicLastTypeNameForTestingRegisterABI{})
102	if r4a != a2 {
103		t.Errorf("bad method value call: got %#v, want %#v", r4a, a2)
104	}
105	if r4b != &vb {
106		t.Errorf("bad method value call: got %#v, want %#v", r4b, &vb)
107	}
108	if s.Value != 5 {
109		t.Errorf("bad method value call: failed to set s.Value: got %d, want %d", s.Value, 5)
110	}
111}
112
113type StructWithMethods struct {
114	Value int
115}
116
117type StructFewRegs struct {
118	a0, a1, a2, a3 int
119	f0, f1, f2, f3 float64
120}
121
122type StructFillRegs struct {
123	a0, a1, a2, a3, a4, a5, a6, a7, a8                              int
124	f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14 float64
125}
126
127func (m *StructWithMethods) AllRegsCall(s StructFewRegs, _ MagicLastTypeNameForTestingRegisterABI) StructFewRegs {
128	m.Value = 1
129	return s
130}
131
132func (m *StructWithMethods) RegsAndStackCall(s StructFewRegs, a [4]uint64, _ MagicLastTypeNameForTestingRegisterABI) (StructFewRegs, [4]uint64) {
133	m.Value = 2
134	return s, a
135}
136
137func (m *StructWithMethods) SpillStructCall(s StructFillRegs, _ MagicLastTypeNameForTestingRegisterABI) StructFillRegs {
138	m.Value = 3
139	return s
140}
141
142// When called as a method value, i is passed on the stack.
143// When called as a method, i is passed in a register.
144func (m *StructWithMethods) ValueRegMethodSpillInt(s StructFillRegs, i int, _ MagicLastTypeNameForTestingRegisterABI) (StructFillRegs, int) {
145	m.Value = 4
146	return s, i
147}
148
149// When called as a method value, i is passed on the stack.
150// When called as a method, i is passed in a register.
151func (m *StructWithMethods) ValueRegMethodSpillPtr(s StructFillRegs, i *byte, _ MagicLastTypeNameForTestingRegisterABI) (StructFillRegs, *byte) {
152	m.Value = 5
153	return s, i
154}
155
156func TestReflectCallABI(t *testing.T) {
157	// Enable register-based reflect.Call and ensure we don't
158	// use potentially incorrect cached versions by clearing
159	// the cache before we start and after we're done.
160	defer reflect.SetArgRegs(reflect.SetArgRegs(abi.IntArgRegs, abi.FloatArgRegs, abi.EffectiveFloatRegSize))
161
162	// Execute the functions defined below which all have the
163	// same form and perform the same function: pass all arguments
164	// to return values. The purpose is to test the call boundary
165	// and make sure it works.
166	r := rand.New(rand.NewSource(genValueRandSeed))
167	for _, fn := range abiCallTestCases {
168		fn := reflect.ValueOf(fn)
169		t.Run(runtime.FuncForPC(fn.Pointer()).Name(), func(t *testing.T) {
170			typ := fn.Type()
171			if typ.Kind() != reflect.Func {
172				t.Fatalf("test case is not a function, has type: %s", typ.String())
173			}
174			if typ.NumIn() != typ.NumOut() {
175				t.Fatalf("test case has different number of inputs and outputs: %d in, %d out", typ.NumIn(), typ.NumOut())
176			}
177			var args []reflect.Value
178			for i := 0; i < typ.NumIn(); i++ {
179				args = append(args, genValue(t, typ.In(i), r))
180			}
181			results := fn.Call(args)
182			for i := range results {
183				x, y := args[i].Interface(), results[i].Interface()
184				if reflect.DeepEqual(x, y) {
185					continue
186				}
187				t.Errorf("arg and result %d differ: got %+v, want %+v", i, y, x)
188			}
189		})
190	}
191}
192
193func TestReflectMakeFuncCallABI(t *testing.T) {
194	// Enable register-based reflect.MakeFunc and ensure we don't
195	// use potentially incorrect cached versions by clearing
196	// the cache before we start and after we're done.
197	defer reflect.SetArgRegs(reflect.SetArgRegs(abi.IntArgRegs, abi.FloatArgRegs, abi.EffectiveFloatRegSize))
198
199	// Execute the functions defined below which all have the
200	// same form and perform the same function: pass all arguments
201	// to return values. The purpose is to test the call boundary
202	// and make sure it works.
203	r := rand.New(rand.NewSource(genValueRandSeed))
204	makeFuncHandler := func(args []reflect.Value) []reflect.Value {
205		if len(args) == 0 {
206			return []reflect.Value{}
207		}
208		return args[:len(args)-1] // The last Value is an empty magic value.
209	}
210	for _, callFn := range abiMakeFuncTestCases {
211		fnTyp := reflect.TypeOf(callFn).In(0)
212		fn := reflect.MakeFunc(fnTyp, makeFuncHandler)
213		callFn := reflect.ValueOf(callFn)
214		t.Run(runtime.FuncForPC(callFn.Pointer()).Name(), func(t *testing.T) {
215			args := []reflect.Value{fn}
216			for i := 0; i < fnTyp.NumIn()-1; /* last one is magic type */ i++ {
217				args = append(args, genValue(t, fnTyp.In(i), r))
218			}
219			results := callFn.Call(args)
220			for i := range results {
221				x, y := args[i+1].Interface(), results[i].Interface()
222				if reflect.DeepEqual(x, y) {
223					continue
224				}
225				t.Errorf("arg and result %d differ: got %+v, want %+v", i, y, x)
226			}
227		})
228	}
229	t.Run("OnlyPointerInRegisterGC", func(t *testing.T) {
230		// This test attempts to induce a failure wherein
231		// the last pointer to an object is passed via registers.
232		// If makeFuncStub doesn't successfully store the pointer
233		// to a location visible to the GC, the object should be
234		// freed and then the next GC should notice that an object
235		// was inexplicably revived.
236		var f func(b *uint64, _ MagicLastTypeNameForTestingRegisterABI) *uint64
237		mkfn := reflect.MakeFunc(reflect.TypeOf(f), func(args []reflect.Value) []reflect.Value {
238			*(args[0].Interface().(*uint64)) = 5
239			return args[:1]
240		})
241		fn := mkfn.Interface().(func(*uint64, MagicLastTypeNameForTestingRegisterABI) *uint64)
242
243		// Call the MakeFunc'd function while trying pass the only pointer
244		// to a new heap-allocated uint64.
245		*reflect.CallGC = true
246		x := fn(new(uint64), MagicLastTypeNameForTestingRegisterABI{})
247		*reflect.CallGC = false
248
249		// Check for bad pointers (which should be x if things went wrong).
250		runtime.GC()
251
252		// Sanity check x.
253		if *x != 5 {
254			t.Fatalf("failed to set value in object")
255		}
256	})
257}
258
259var abiCallTestCases = []any{
260	passNone,
261	passInt,
262	passInt8,
263	passInt16,
264	passInt32,
265	passInt64,
266	passUint,
267	passUint8,
268	passUint16,
269	passUint32,
270	passUint64,
271	passFloat32,
272	passFloat64,
273	passComplex64,
274	passComplex128,
275	passManyInt,
276	passManyFloat64,
277	passArray1,
278	passArray,
279	passArray1Mix,
280	passString,
281	// TODO(mknyszek): Test passing interface values.
282	passSlice,
283	passPointer,
284	passStruct1,
285	passStruct2,
286	passStruct3,
287	passStruct4,
288	passStruct5,
289	passStruct6,
290	passStruct7,
291	passStruct8,
292	passStruct9,
293	passStruct10,
294	// TODO(mknyszek): Test passing unsafe.Pointer values.
295	// TODO(mknyszek): Test passing chan values.
296	passStruct11,
297	passStruct12,
298	passStruct13,
299	passStruct14,
300	passStruct15,
301	pass2Struct1,
302	passEmptyStruct,
303	passStruct10AndSmall,
304}
305
306// Functions for testing reflect function call functionality.
307
308//go:registerparams
309//go:noinline
310func passNone() {}
311
312//go:registerparams
313//go:noinline
314func passInt(a int) int {
315	return a
316}
317
318//go:registerparams
319//go:noinline
320func passInt8(a int8) int8 {
321	return a
322}
323
324//go:registerparams
325//go:noinline
326func passInt16(a int16) int16 {
327	return a
328}
329
330//go:registerparams
331//go:noinline
332func passInt32(a int32) int32 {
333	return a
334}
335
336//go:registerparams
337//go:noinline
338func passInt64(a int64) int64 {
339	return a
340}
341
342//go:registerparams
343//go:noinline
344func passUint(a uint) uint {
345	return a
346}
347
348//go:registerparams
349//go:noinline
350func passUint8(a uint8) uint8 {
351	return a
352}
353
354//go:registerparams
355//go:noinline
356func passUint16(a uint16) uint16 {
357	return a
358}
359
360//go:registerparams
361//go:noinline
362func passUint32(a uint32) uint32 {
363	return a
364}
365
366//go:registerparams
367//go:noinline
368func passUint64(a uint64) uint64 {
369	return a
370}
371
372//go:registerparams
373//go:noinline
374func passFloat32(a float32) float32 {
375	return a
376}
377
378//go:registerparams
379//go:noinline
380func passFloat64(a float64) float64 {
381	return a
382}
383
384//go:registerparams
385//go:noinline
386func passComplex64(a complex64) complex64 {
387	return a
388}
389
390//go:registerparams
391//go:noinline
392func passComplex128(a complex128) complex128 {
393	return a
394}
395
396//go:registerparams
397//go:noinline
398func passArray1(a [1]uint32) [1]uint32 {
399	return a
400}
401
402//go:registerparams
403//go:noinline
404func passArray(a [2]uintptr) [2]uintptr {
405	return a
406}
407
408//go:registerparams
409//go:noinline
410func passArray1Mix(a int, b [1]uint32, c float64) (int, [1]uint32, float64) {
411	return a, b, c
412}
413
414//go:registerparams
415//go:noinline
416func passString(a string) string {
417	return a
418}
419
420//go:registerparams
421//go:noinline
422func passSlice(a []byte) []byte {
423	return a
424}
425
426//go:registerparams
427//go:noinline
428func passPointer(a *byte) *byte {
429	return a
430}
431
432//go:registerparams
433//go:noinline
434func passManyInt(a, b, c, d, e, f, g, h, i, j int) (int, int, int, int, int, int, int, int, int, int) {
435	return a, b, c, d, e, f, g, h, i, j
436}
437
438//go:registerparams
439//go:noinline
440func passManyFloat64(a, b, c, d, e, f, g, h, i, j, l, m, n, o, p, q, r, s, t float64) (float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64) {
441	return a, b, c, d, e, f, g, h, i, j, l, m, n, o, p, q, r, s, t
442}
443
444//go:registerparams
445//go:noinline
446func passStruct1(a Struct1) Struct1 {
447	return a
448}
449
450//go:registerparams
451//go:noinline
452func passStruct2(a Struct2) Struct2 {
453	return a
454}
455
456//go:registerparams
457//go:noinline
458func passStruct3(a Struct3) Struct3 {
459	return a
460}
461
462//go:registerparams
463//go:noinline
464func passStruct4(a Struct4) Struct4 {
465	return a
466}
467
468//go:registerparams
469//go:noinline
470func passStruct5(a Struct5) Struct5 {
471	return a
472}
473
474//go:registerparams
475//go:noinline
476func passStruct6(a Struct6) Struct6 {
477	return a
478}
479
480//go:registerparams
481//go:noinline
482func passStruct7(a Struct7) Struct7 {
483	return a
484}
485
486//go:registerparams
487//go:noinline
488func passStruct8(a Struct8) Struct8 {
489	return a
490}
491
492//go:registerparams
493//go:noinline
494func passStruct9(a Struct9) Struct9 {
495	return a
496}
497
498//go:registerparams
499//go:noinline
500func passStruct10(a Struct10) Struct10 {
501	return a
502}
503
504//go:registerparams
505//go:noinline
506func passStruct11(a Struct11) Struct11 {
507	return a
508}
509
510//go:registerparams
511//go:noinline
512func passStruct12(a Struct12) Struct12 {
513	return a
514}
515
516//go:registerparams
517//go:noinline
518func passStruct13(a Struct13) Struct13 {
519	return a
520}
521
522//go:registerparams
523//go:noinline
524func passStruct14(a Struct14) Struct14 {
525	return a
526}
527
528//go:registerparams
529//go:noinline
530func passStruct15(a Struct15) Struct15 {
531	return a
532}
533
534//go:registerparams
535//go:noinline
536func pass2Struct1(a, b Struct1) (x, y Struct1) {
537	return a, b
538}
539
540//go:registerparams
541//go:noinline
542func passEmptyStruct(a int, b struct{}, c float64) (int, struct{}, float64) {
543	return a, b, c
544}
545
546// This test case forces a large argument to the stack followed by more
547// in-register arguments.
548//
549//go:registerparams
550//go:noinline
551func passStruct10AndSmall(a Struct10, b byte, c uint) (Struct10, byte, uint) {
552	return a, b, c
553}
554
555var abiMakeFuncTestCases = []any{
556	callArgsNone,
557	callArgsInt,
558	callArgsInt8,
559	callArgsInt16,
560	callArgsInt32,
561	callArgsInt64,
562	callArgsUint,
563	callArgsUint8,
564	callArgsUint16,
565	callArgsUint32,
566	callArgsUint64,
567	callArgsFloat32,
568	callArgsFloat64,
569	callArgsComplex64,
570	callArgsComplex128,
571	callArgsManyInt,
572	callArgsManyFloat64,
573	callArgsArray1,
574	callArgsArray,
575	callArgsArray1Mix,
576	callArgsString,
577	// TODO(mknyszek): Test callArgsing interface values.
578	callArgsSlice,
579	callArgsPointer,
580	callArgsStruct1,
581	callArgsStruct2,
582	callArgsStruct3,
583	callArgsStruct4,
584	callArgsStruct5,
585	callArgsStruct6,
586	callArgsStruct7,
587	callArgsStruct8,
588	callArgsStruct9,
589	callArgsStruct10,
590	// TODO(mknyszek): Test callArgsing unsafe.Pointer values.
591	// TODO(mknyszek): Test callArgsing chan values.
592	callArgsStruct11,
593	callArgsStruct12,
594	callArgsStruct13,
595	callArgsStruct14,
596	callArgsStruct15,
597	callArgs2Struct1,
598	callArgsEmptyStruct,
599}
600
601//go:registerparams
602//go:noinline
603func callArgsNone(f func(MagicLastTypeNameForTestingRegisterABI)) {
604	f(MagicLastTypeNameForTestingRegisterABI{})
605}
606
607//go:registerparams
608//go:noinline
609func callArgsInt(f func(int, MagicLastTypeNameForTestingRegisterABI) int, a0 int) int {
610	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
611}
612
613//go:registerparams
614//go:noinline
615func callArgsInt8(f func(int8, MagicLastTypeNameForTestingRegisterABI) int8, a0 int8) int8 {
616	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
617}
618
619//go:registerparams
620//go:noinline
621func callArgsInt16(f func(int16, MagicLastTypeNameForTestingRegisterABI) int16, a0 int16) int16 {
622	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
623}
624
625//go:registerparams
626//go:noinline
627func callArgsInt32(f func(int32, MagicLastTypeNameForTestingRegisterABI) int32, a0 int32) int32 {
628	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
629}
630
631//go:registerparams
632//go:noinline
633func callArgsInt64(f func(int64, MagicLastTypeNameForTestingRegisterABI) int64, a0 int64) int64 {
634	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
635}
636
637//go:registerparams
638//go:noinline
639func callArgsUint(f func(uint, MagicLastTypeNameForTestingRegisterABI) uint, a0 uint) uint {
640	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
641}
642
643//go:registerparams
644//go:noinline
645func callArgsUint8(f func(uint8, MagicLastTypeNameForTestingRegisterABI) uint8, a0 uint8) uint8 {
646	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
647}
648
649//go:registerparams
650//go:noinline
651func callArgsUint16(f func(uint16, MagicLastTypeNameForTestingRegisterABI) uint16, a0 uint16) uint16 {
652	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
653}
654
655//go:registerparams
656//go:noinline
657func callArgsUint32(f func(uint32, MagicLastTypeNameForTestingRegisterABI) uint32, a0 uint32) uint32 {
658	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
659}
660
661//go:registerparams
662//go:noinline
663func callArgsUint64(f func(uint64, MagicLastTypeNameForTestingRegisterABI) uint64, a0 uint64) uint64 {
664	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
665}
666
667//go:registerparams
668//go:noinline
669func callArgsFloat32(f func(float32, MagicLastTypeNameForTestingRegisterABI) float32, a0 float32) float32 {
670	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
671}
672
673//go:registerparams
674//go:noinline
675func callArgsFloat64(f func(float64, MagicLastTypeNameForTestingRegisterABI) float64, a0 float64) float64 {
676	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
677}
678
679//go:registerparams
680//go:noinline
681func callArgsComplex64(f func(complex64, MagicLastTypeNameForTestingRegisterABI) complex64, a0 complex64) complex64 {
682	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
683}
684
685//go:registerparams
686//go:noinline
687func callArgsComplex128(f func(complex128, MagicLastTypeNameForTestingRegisterABI) complex128, a0 complex128) complex128 {
688	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
689}
690
691//go:registerparams
692//go:noinline
693func callArgsArray1(f func([1]uint32, MagicLastTypeNameForTestingRegisterABI) [1]uint32, a0 [1]uint32) [1]uint32 {
694	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
695}
696
697//go:registerparams
698//go:noinline
699func callArgsArray(f func([2]uintptr, MagicLastTypeNameForTestingRegisterABI) [2]uintptr, a0 [2]uintptr) [2]uintptr {
700	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
701}
702
703//go:registerparams
704//go:noinline
705func callArgsArray1Mix(f func(int, [1]uint32, float64, MagicLastTypeNameForTestingRegisterABI) (int, [1]uint32, float64), a0 int, a1 [1]uint32, a2 float64) (int, [1]uint32, float64) {
706	return f(a0, a1, a2, MagicLastTypeNameForTestingRegisterABI{})
707}
708
709//go:registerparams
710//go:noinline
711func callArgsString(f func(string, MagicLastTypeNameForTestingRegisterABI) string, a0 string) string {
712	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
713}
714
715//go:registerparams
716//go:noinline
717func callArgsSlice(f func([]byte, MagicLastTypeNameForTestingRegisterABI) []byte, a0 []byte) []byte {
718	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
719}
720
721//go:registerparams
722//go:noinline
723func callArgsPointer(f func(*byte, MagicLastTypeNameForTestingRegisterABI) *byte, a0 *byte) *byte {
724	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
725}
726
727//go:registerparams
728//go:noinline
729func callArgsManyInt(f func(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 int, x MagicLastTypeNameForTestingRegisterABI) (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9 int), a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 int) (int, int, int, int, int, int, int, int, int, int) {
730	return f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, MagicLastTypeNameForTestingRegisterABI{})
731}
732
733//go:registerparams
734//go:noinline
735func callArgsManyFloat64(f func(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 float64, x MagicLastTypeNameForTestingRegisterABI) (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18 float64), a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 float64) (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18 float64) {
736	return f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, MagicLastTypeNameForTestingRegisterABI{})
737}
738
739//go:registerparams
740//go:noinline
741func callArgsStruct1(f func(Struct1, MagicLastTypeNameForTestingRegisterABI) Struct1, a0 Struct1) Struct1 {
742	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
743}
744
745//go:registerparams
746//go:noinline
747func callArgsStruct2(f func(Struct2, MagicLastTypeNameForTestingRegisterABI) Struct2, a0 Struct2) Struct2 {
748	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
749}
750
751//go:registerparams
752//go:noinline
753func callArgsStruct3(f func(Struct3, MagicLastTypeNameForTestingRegisterABI) Struct3, a0 Struct3) Struct3 {
754	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
755}
756
757//go:registerparams
758//go:noinline
759func callArgsStruct4(f func(Struct4, MagicLastTypeNameForTestingRegisterABI) Struct4, a0 Struct4) Struct4 {
760	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
761}
762
763//go:registerparams
764//go:noinline
765func callArgsStruct5(f func(Struct5, MagicLastTypeNameForTestingRegisterABI) Struct5, a0 Struct5) Struct5 {
766	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
767}
768
769//go:registerparams
770//go:noinline
771func callArgsStruct6(f func(Struct6, MagicLastTypeNameForTestingRegisterABI) Struct6, a0 Struct6) Struct6 {
772	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
773}
774
775//go:registerparams
776//go:noinline
777func callArgsStruct7(f func(Struct7, MagicLastTypeNameForTestingRegisterABI) Struct7, a0 Struct7) Struct7 {
778	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
779}
780
781//go:registerparams
782//go:noinline
783func callArgsStruct8(f func(Struct8, MagicLastTypeNameForTestingRegisterABI) Struct8, a0 Struct8) Struct8 {
784	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
785}
786
787//go:registerparams
788//go:noinline
789func callArgsStruct9(f func(Struct9, MagicLastTypeNameForTestingRegisterABI) Struct9, a0 Struct9) Struct9 {
790	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
791}
792
793//go:registerparams
794//go:noinline
795func callArgsStruct10(f func(Struct10, MagicLastTypeNameForTestingRegisterABI) Struct10, a0 Struct10) Struct10 {
796	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
797}
798
799//go:registerparams
800//go:noinline
801func callArgsStruct11(f func(Struct11, MagicLastTypeNameForTestingRegisterABI) Struct11, a0 Struct11) Struct11 {
802	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
803}
804
805//go:registerparams
806//go:noinline
807func callArgsStruct12(f func(Struct12, MagicLastTypeNameForTestingRegisterABI) Struct12, a0 Struct12) Struct12 {
808	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
809}
810
811//go:registerparams
812//go:noinline
813func callArgsStruct13(f func(Struct13, MagicLastTypeNameForTestingRegisterABI) Struct13, a0 Struct13) Struct13 {
814	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
815}
816
817//go:registerparams
818//go:noinline
819func callArgsStruct14(f func(Struct14, MagicLastTypeNameForTestingRegisterABI) Struct14, a0 Struct14) Struct14 {
820	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
821}
822
823//go:registerparams
824//go:noinline
825func callArgsStruct15(f func(Struct15, MagicLastTypeNameForTestingRegisterABI) Struct15, a0 Struct15) Struct15 {
826	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
827}
828
829//go:registerparams
830//go:noinline
831func callArgs2Struct1(f func(Struct1, Struct1, MagicLastTypeNameForTestingRegisterABI) (Struct1, Struct1), a0, a1 Struct1) (r0, r1 Struct1) {
832	return f(a0, a1, MagicLastTypeNameForTestingRegisterABI{})
833}
834
835//go:registerparams
836//go:noinline
837func callArgsEmptyStruct(f func(int, struct{}, float64, MagicLastTypeNameForTestingRegisterABI) (int, struct{}, float64), a0 int, a1 struct{}, a2 float64) (int, struct{}, float64) {
838	return f(a0, a1, a2, MagicLastTypeNameForTestingRegisterABI{})
839}
840
841// Struct1 is a simple integer-only aggregate struct.
842type Struct1 struct {
843	A, B, C uint
844}
845
846// Struct2 is Struct1 but with an array-typed field that will
847// force it to get passed on the stack.
848type Struct2 struct {
849	A, B, C uint
850	D       [2]uint32
851}
852
853// Struct3 is Struct2 but with an anonymous array-typed field.
854// This should act identically to Struct2.
855type Struct3 struct {
856	A, B, C uint
857	D       [2]uint32
858}
859
860// Struct4 has byte-length fields that should
861// each use up a whole registers.
862type Struct4 struct {
863	A, B int8
864	C, D uint8
865	E    bool
866}
867
868// Struct5 is a relatively large struct
869// with both integer and floating point values.
870type Struct5 struct {
871	A             uint16
872	B             int16
873	C, D          uint32
874	E             int32
875	F, G, H, I, J float32
876}
877
878// Struct6 has a nested struct.
879type Struct6 struct {
880	Struct1
881}
882
883// Struct7 is a struct with a nested array-typed field
884// that cannot be passed in registers as a result.
885type Struct7 struct {
886	Struct1
887	Struct2
888}
889
890// Struct8 is large aggregate struct type that may be
891// passed in registers.
892type Struct8 struct {
893	Struct5
894	Struct1
895}
896
897// Struct9 is a type that has an array type nested
898// 2 layers deep, and as a result needs to be passed
899// on the stack.
900type Struct9 struct {
901	Struct1
902	Struct7
903}
904
905// Struct10 is a struct type that is too large to be
906// passed in registers.
907type Struct10 struct {
908	Struct5
909	Struct8
910}
911
912// Struct11 is a struct type that has several reference
913// types in it.
914type Struct11 struct {
915	X map[string]int
916}
917
918// Struct12 has Struct11 embedded into it to test more
919// paths.
920type Struct12 struct {
921	A int
922	Struct11
923}
924
925// Struct13 tests an empty field.
926type Struct13 struct {
927	A int
928	X struct{}
929	B int
930}
931
932// Struct14 tests a non-zero-sized (and otherwise register-assignable)
933// struct with a field that is a non-zero length array with zero-sized members.
934type Struct14 struct {
935	A uintptr
936	X [3]struct{}
937	B float64
938}
939
940// Struct15 tests a non-zero-sized (and otherwise register-assignable)
941// struct with a struct field that is zero-sized but contains a
942// non-zero length array with zero-sized members.
943type Struct15 struct {
944	A uintptr
945	X struct {
946		Y [3]struct{}
947	}
948	B float64
949}
950
951const genValueRandSeed = 0
952
953// genValue generates a pseudorandom reflect.Value with type t.
954// The reflect.Value produced by this function is always the same
955// for the same type.
956func genValue(t *testing.T, typ reflect.Type, r *rand.Rand) reflect.Value {
957	// Re-seed and reset the PRNG because we want each value with the
958	// same type to be the same random value.
959	r.Seed(genValueRandSeed)
960	v, ok := quick.Value(typ, r)
961	if !ok {
962		t.Fatal("failed to generate value")
963	}
964	return v
965}
966
967func TestSignalingNaNArgument(t *testing.T) {
968	v := reflect.ValueOf(func(x float32) {
969		// make sure x is a signaling NaN.
970		u := math.Float32bits(x)
971		if u != snan {
972			t.Fatalf("signaling NaN not correct: %x\n", u)
973		}
974	})
975	v.Call([]reflect.Value{reflect.ValueOf(math.Float32frombits(snan))})
976}
977
978func TestSignalingNaNReturn(t *testing.T) {
979	v := reflect.ValueOf(func() float32 {
980		return math.Float32frombits(snan)
981	})
982	var x float32
983	reflect.ValueOf(&x).Elem().Set(v.Call(nil)[0])
984	// make sure x is a signaling NaN.
985	u := math.Float32bits(x)
986	if u != snan {
987		t.Fatalf("signaling NaN not correct: %x\n", u)
988	}
989}
990