Source file src/reflect/abi_test.go

     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.regabireflect && goexperiment.regabiargs
     6  
     7  package reflect_test
     8  
     9  import (
    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.
    22  type MagicLastTypeNameForTestingRegisterABI struct{}
    23  
    24  func 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  
   113  type StructWithMethods struct {
   114  	Value int
   115  }
   116  
   117  type StructFewRegs struct {
   118  	a0, a1, a2, a3 int
   119  	f0, f1, f2, f3 float64
   120  }
   121  
   122  type 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  
   127  func (m *StructWithMethods) AllRegsCall(s StructFewRegs, _ MagicLastTypeNameForTestingRegisterABI) StructFewRegs {
   128  	m.Value = 1
   129  	return s
   130  }
   131  
   132  func (m *StructWithMethods) RegsAndStackCall(s StructFewRegs, a [4]uint64, _ MagicLastTypeNameForTestingRegisterABI) (StructFewRegs, [4]uint64) {
   133  	m.Value = 2
   134  	return s, a
   135  }
   136  
   137  func (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.
   144  func (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.
   151  func (m *StructWithMethods) ValueRegMethodSpillPtr(s StructFillRegs, i *byte, _ MagicLastTypeNameForTestingRegisterABI) (StructFillRegs, *byte) {
   152  	m.Value = 5
   153  	return s, i
   154  }
   155  
   156  func 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  
   193  func 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  
   259  var 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
   310  func passNone() {}
   311  
   312  //go:registerparams
   313  //go:noinline
   314  func passInt(a int) int {
   315  	return a
   316  }
   317  
   318  //go:registerparams
   319  //go:noinline
   320  func passInt8(a int8) int8 {
   321  	return a
   322  }
   323  
   324  //go:registerparams
   325  //go:noinline
   326  func passInt16(a int16) int16 {
   327  	return a
   328  }
   329  
   330  //go:registerparams
   331  //go:noinline
   332  func passInt32(a int32) int32 {
   333  	return a
   334  }
   335  
   336  //go:registerparams
   337  //go:noinline
   338  func passInt64(a int64) int64 {
   339  	return a
   340  }
   341  
   342  //go:registerparams
   343  //go:noinline
   344  func passUint(a uint) uint {
   345  	return a
   346  }
   347  
   348  //go:registerparams
   349  //go:noinline
   350  func passUint8(a uint8) uint8 {
   351  	return a
   352  }
   353  
   354  //go:registerparams
   355  //go:noinline
   356  func passUint16(a uint16) uint16 {
   357  	return a
   358  }
   359  
   360  //go:registerparams
   361  //go:noinline
   362  func passUint32(a uint32) uint32 {
   363  	return a
   364  }
   365  
   366  //go:registerparams
   367  //go:noinline
   368  func passUint64(a uint64) uint64 {
   369  	return a
   370  }
   371  
   372  //go:registerparams
   373  //go:noinline
   374  func passFloat32(a float32) float32 {
   375  	return a
   376  }
   377  
   378  //go:registerparams
   379  //go:noinline
   380  func passFloat64(a float64) float64 {
   381  	return a
   382  }
   383  
   384  //go:registerparams
   385  //go:noinline
   386  func passComplex64(a complex64) complex64 {
   387  	return a
   388  }
   389  
   390  //go:registerparams
   391  //go:noinline
   392  func passComplex128(a complex128) complex128 {
   393  	return a
   394  }
   395  
   396  //go:registerparams
   397  //go:noinline
   398  func passArray1(a [1]uint32) [1]uint32 {
   399  	return a
   400  }
   401  
   402  //go:registerparams
   403  //go:noinline
   404  func passArray(a [2]uintptr) [2]uintptr {
   405  	return a
   406  }
   407  
   408  //go:registerparams
   409  //go:noinline
   410  func 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
   416  func passString(a string) string {
   417  	return a
   418  }
   419  
   420  //go:registerparams
   421  //go:noinline
   422  func passSlice(a []byte) []byte {
   423  	return a
   424  }
   425  
   426  //go:registerparams
   427  //go:noinline
   428  func passPointer(a *byte) *byte {
   429  	return a
   430  }
   431  
   432  //go:registerparams
   433  //go:noinline
   434  func 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
   440  func 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
   446  func passStruct1(a Struct1) Struct1 {
   447  	return a
   448  }
   449  
   450  //go:registerparams
   451  //go:noinline
   452  func passStruct2(a Struct2) Struct2 {
   453  	return a
   454  }
   455  
   456  //go:registerparams
   457  //go:noinline
   458  func passStruct3(a Struct3) Struct3 {
   459  	return a
   460  }
   461  
   462  //go:registerparams
   463  //go:noinline
   464  func passStruct4(a Struct4) Struct4 {
   465  	return a
   466  }
   467  
   468  //go:registerparams
   469  //go:noinline
   470  func passStruct5(a Struct5) Struct5 {
   471  	return a
   472  }
   473  
   474  //go:registerparams
   475  //go:noinline
   476  func passStruct6(a Struct6) Struct6 {
   477  	return a
   478  }
   479  
   480  //go:registerparams
   481  //go:noinline
   482  func passStruct7(a Struct7) Struct7 {
   483  	return a
   484  }
   485  
   486  //go:registerparams
   487  //go:noinline
   488  func passStruct8(a Struct8) Struct8 {
   489  	return a
   490  }
   491  
   492  //go:registerparams
   493  //go:noinline
   494  func passStruct9(a Struct9) Struct9 {
   495  	return a
   496  }
   497  
   498  //go:registerparams
   499  //go:noinline
   500  func passStruct10(a Struct10) Struct10 {
   501  	return a
   502  }
   503  
   504  //go:registerparams
   505  //go:noinline
   506  func passStruct11(a Struct11) Struct11 {
   507  	return a
   508  }
   509  
   510  //go:registerparams
   511  //go:noinline
   512  func passStruct12(a Struct12) Struct12 {
   513  	return a
   514  }
   515  
   516  //go:registerparams
   517  //go:noinline
   518  func passStruct13(a Struct13) Struct13 {
   519  	return a
   520  }
   521  
   522  //go:registerparams
   523  //go:noinline
   524  func passStruct14(a Struct14) Struct14 {
   525  	return a
   526  }
   527  
   528  //go:registerparams
   529  //go:noinline
   530  func passStruct15(a Struct15) Struct15 {
   531  	return a
   532  }
   533  
   534  //go:registerparams
   535  //go:noinline
   536  func pass2Struct1(a, b Struct1) (x, y Struct1) {
   537  	return a, b
   538  }
   539  
   540  //go:registerparams
   541  //go:noinline
   542  func 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  //go:registerparams
   549  //go:noinline
   550  func passStruct10AndSmall(a Struct10, b byte, c uint) (Struct10, byte, uint) {
   551  	return a, b, c
   552  }
   553  
   554  var abiMakeFuncTestCases = []any{
   555  	callArgsNone,
   556  	callArgsInt,
   557  	callArgsInt8,
   558  	callArgsInt16,
   559  	callArgsInt32,
   560  	callArgsInt64,
   561  	callArgsUint,
   562  	callArgsUint8,
   563  	callArgsUint16,
   564  	callArgsUint32,
   565  	callArgsUint64,
   566  	callArgsFloat32,
   567  	callArgsFloat64,
   568  	callArgsComplex64,
   569  	callArgsComplex128,
   570  	callArgsManyInt,
   571  	callArgsManyFloat64,
   572  	callArgsArray1,
   573  	callArgsArray,
   574  	callArgsArray1Mix,
   575  	callArgsString,
   576  	// TODO(mknyszek): Test callArgsing interface values.
   577  	callArgsSlice,
   578  	callArgsPointer,
   579  	callArgsStruct1,
   580  	callArgsStruct2,
   581  	callArgsStruct3,
   582  	callArgsStruct4,
   583  	callArgsStruct5,
   584  	callArgsStruct6,
   585  	callArgsStruct7,
   586  	callArgsStruct8,
   587  	callArgsStruct9,
   588  	callArgsStruct10,
   589  	// TODO(mknyszek): Test callArgsing unsafe.Pointer values.
   590  	// TODO(mknyszek): Test callArgsing chan values.
   591  	callArgsStruct11,
   592  	callArgsStruct12,
   593  	callArgsStruct13,
   594  	callArgsStruct14,
   595  	callArgsStruct15,
   596  	callArgs2Struct1,
   597  	callArgsEmptyStruct,
   598  }
   599  
   600  //go:registerparams
   601  //go:noinline
   602  func callArgsNone(f func(MagicLastTypeNameForTestingRegisterABI)) {
   603  	f(MagicLastTypeNameForTestingRegisterABI{})
   604  }
   605  
   606  //go:registerparams
   607  //go:noinline
   608  func callArgsInt(f func(int, MagicLastTypeNameForTestingRegisterABI) int, a0 int) int {
   609  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   610  }
   611  
   612  //go:registerparams
   613  //go:noinline
   614  func callArgsInt8(f func(int8, MagicLastTypeNameForTestingRegisterABI) int8, a0 int8) int8 {
   615  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   616  }
   617  
   618  //go:registerparams
   619  //go:noinline
   620  func callArgsInt16(f func(int16, MagicLastTypeNameForTestingRegisterABI) int16, a0 int16) int16 {
   621  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   622  }
   623  
   624  //go:registerparams
   625  //go:noinline
   626  func callArgsInt32(f func(int32, MagicLastTypeNameForTestingRegisterABI) int32, a0 int32) int32 {
   627  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   628  }
   629  
   630  //go:registerparams
   631  //go:noinline
   632  func callArgsInt64(f func(int64, MagicLastTypeNameForTestingRegisterABI) int64, a0 int64) int64 {
   633  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   634  }
   635  
   636  //go:registerparams
   637  //go:noinline
   638  func callArgsUint(f func(uint, MagicLastTypeNameForTestingRegisterABI) uint, a0 uint) uint {
   639  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   640  }
   641  
   642  //go:registerparams
   643  //go:noinline
   644  func callArgsUint8(f func(uint8, MagicLastTypeNameForTestingRegisterABI) uint8, a0 uint8) uint8 {
   645  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   646  }
   647  
   648  //go:registerparams
   649  //go:noinline
   650  func callArgsUint16(f func(uint16, MagicLastTypeNameForTestingRegisterABI) uint16, a0 uint16) uint16 {
   651  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   652  }
   653  
   654  //go:registerparams
   655  //go:noinline
   656  func callArgsUint32(f func(uint32, MagicLastTypeNameForTestingRegisterABI) uint32, a0 uint32) uint32 {
   657  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   658  }
   659  
   660  //go:registerparams
   661  //go:noinline
   662  func callArgsUint64(f func(uint64, MagicLastTypeNameForTestingRegisterABI) uint64, a0 uint64) uint64 {
   663  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   664  }
   665  
   666  //go:registerparams
   667  //go:noinline
   668  func callArgsFloat32(f func(float32, MagicLastTypeNameForTestingRegisterABI) float32, a0 float32) float32 {
   669  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   670  }
   671  
   672  //go:registerparams
   673  //go:noinline
   674  func callArgsFloat64(f func(float64, MagicLastTypeNameForTestingRegisterABI) float64, a0 float64) float64 {
   675  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   676  }
   677  
   678  //go:registerparams
   679  //go:noinline
   680  func callArgsComplex64(f func(complex64, MagicLastTypeNameForTestingRegisterABI) complex64, a0 complex64) complex64 {
   681  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   682  }
   683  
   684  //go:registerparams
   685  //go:noinline
   686  func callArgsComplex128(f func(complex128, MagicLastTypeNameForTestingRegisterABI) complex128, a0 complex128) complex128 {
   687  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   688  }
   689  
   690  //go:registerparams
   691  //go:noinline
   692  func callArgsArray1(f func([1]uint32, MagicLastTypeNameForTestingRegisterABI) [1]uint32, a0 [1]uint32) [1]uint32 {
   693  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   694  }
   695  
   696  //go:registerparams
   697  //go:noinline
   698  func callArgsArray(f func([2]uintptr, MagicLastTypeNameForTestingRegisterABI) [2]uintptr, a0 [2]uintptr) [2]uintptr {
   699  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   700  }
   701  
   702  //go:registerparams
   703  //go:noinline
   704  func callArgsArray1Mix(f func(int, [1]uint32, float64, MagicLastTypeNameForTestingRegisterABI) (int, [1]uint32, float64), a0 int, a1 [1]uint32, a2 float64) (int, [1]uint32, float64) {
   705  	return f(a0, a1, a2, MagicLastTypeNameForTestingRegisterABI{})
   706  }
   707  
   708  //go:registerparams
   709  //go:noinline
   710  func callArgsString(f func(string, MagicLastTypeNameForTestingRegisterABI) string, a0 string) string {
   711  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   712  }
   713  
   714  //go:registerparams
   715  //go:noinline
   716  func callArgsSlice(f func([]byte, MagicLastTypeNameForTestingRegisterABI) []byte, a0 []byte) []byte {
   717  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   718  }
   719  
   720  //go:registerparams
   721  //go:noinline
   722  func callArgsPointer(f func(*byte, MagicLastTypeNameForTestingRegisterABI) *byte, a0 *byte) *byte {
   723  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   724  }
   725  
   726  //go:registerparams
   727  //go:noinline
   728  func 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) {
   729  	return f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, MagicLastTypeNameForTestingRegisterABI{})
   730  }
   731  
   732  //go:registerparams
   733  //go:noinline
   734  func 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) {
   735  	return f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, MagicLastTypeNameForTestingRegisterABI{})
   736  }
   737  
   738  //go:registerparams
   739  //go:noinline
   740  func callArgsStruct1(f func(Struct1, MagicLastTypeNameForTestingRegisterABI) Struct1, a0 Struct1) Struct1 {
   741  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   742  }
   743  
   744  //go:registerparams
   745  //go:noinline
   746  func callArgsStruct2(f func(Struct2, MagicLastTypeNameForTestingRegisterABI) Struct2, a0 Struct2) Struct2 {
   747  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   748  }
   749  
   750  //go:registerparams
   751  //go:noinline
   752  func callArgsStruct3(f func(Struct3, MagicLastTypeNameForTestingRegisterABI) Struct3, a0 Struct3) Struct3 {
   753  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   754  }
   755  
   756  //go:registerparams
   757  //go:noinline
   758  func callArgsStruct4(f func(Struct4, MagicLastTypeNameForTestingRegisterABI) Struct4, a0 Struct4) Struct4 {
   759  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   760  }
   761  
   762  //go:registerparams
   763  //go:noinline
   764  func callArgsStruct5(f func(Struct5, MagicLastTypeNameForTestingRegisterABI) Struct5, a0 Struct5) Struct5 {
   765  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   766  }
   767  
   768  //go:registerparams
   769  //go:noinline
   770  func callArgsStruct6(f func(Struct6, MagicLastTypeNameForTestingRegisterABI) Struct6, a0 Struct6) Struct6 {
   771  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   772  }
   773  
   774  //go:registerparams
   775  //go:noinline
   776  func callArgsStruct7(f func(Struct7, MagicLastTypeNameForTestingRegisterABI) Struct7, a0 Struct7) Struct7 {
   777  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   778  }
   779  
   780  //go:registerparams
   781  //go:noinline
   782  func callArgsStruct8(f func(Struct8, MagicLastTypeNameForTestingRegisterABI) Struct8, a0 Struct8) Struct8 {
   783  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   784  }
   785  
   786  //go:registerparams
   787  //go:noinline
   788  func callArgsStruct9(f func(Struct9, MagicLastTypeNameForTestingRegisterABI) Struct9, a0 Struct9) Struct9 {
   789  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   790  }
   791  
   792  //go:registerparams
   793  //go:noinline
   794  func callArgsStruct10(f func(Struct10, MagicLastTypeNameForTestingRegisterABI) Struct10, a0 Struct10) Struct10 {
   795  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   796  }
   797  
   798  //go:registerparams
   799  //go:noinline
   800  func callArgsStruct11(f func(Struct11, MagicLastTypeNameForTestingRegisterABI) Struct11, a0 Struct11) Struct11 {
   801  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   802  }
   803  
   804  //go:registerparams
   805  //go:noinline
   806  func callArgsStruct12(f func(Struct12, MagicLastTypeNameForTestingRegisterABI) Struct12, a0 Struct12) Struct12 {
   807  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   808  }
   809  
   810  //go:registerparams
   811  //go:noinline
   812  func callArgsStruct13(f func(Struct13, MagicLastTypeNameForTestingRegisterABI) Struct13, a0 Struct13) Struct13 {
   813  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   814  }
   815  
   816  //go:registerparams
   817  //go:noinline
   818  func callArgsStruct14(f func(Struct14, MagicLastTypeNameForTestingRegisterABI) Struct14, a0 Struct14) Struct14 {
   819  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   820  }
   821  
   822  //go:registerparams
   823  //go:noinline
   824  func callArgsStruct15(f func(Struct15, MagicLastTypeNameForTestingRegisterABI) Struct15, a0 Struct15) Struct15 {
   825  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   826  }
   827  
   828  //go:registerparams
   829  //go:noinline
   830  func callArgs2Struct1(f func(Struct1, Struct1, MagicLastTypeNameForTestingRegisterABI) (Struct1, Struct1), a0, a1 Struct1) (r0, r1 Struct1) {
   831  	return f(a0, a1, MagicLastTypeNameForTestingRegisterABI{})
   832  }
   833  
   834  //go:registerparams
   835  //go:noinline
   836  func callArgsEmptyStruct(f func(int, struct{}, float64, MagicLastTypeNameForTestingRegisterABI) (int, struct{}, float64), a0 int, a1 struct{}, a2 float64) (int, struct{}, float64) {
   837  	return f(a0, a1, a2, MagicLastTypeNameForTestingRegisterABI{})
   838  }
   839  
   840  // Struct1 is a simple integer-only aggregate struct.
   841  type Struct1 struct {
   842  	A, B, C uint
   843  }
   844  
   845  // Struct2 is Struct1 but with an array-typed field that will
   846  // force it to get passed on the stack.
   847  type Struct2 struct {
   848  	A, B, C uint
   849  	D       [2]uint32
   850  }
   851  
   852  // Struct3 is Struct2 but with an anonymous array-typed field.
   853  // This should act identically to Struct2.
   854  type Struct3 struct {
   855  	A, B, C uint
   856  	D       [2]uint32
   857  }
   858  
   859  // Struct4 has byte-length fields that should
   860  // each use up a whole registers.
   861  type Struct4 struct {
   862  	A, B int8
   863  	C, D uint8
   864  	E    bool
   865  }
   866  
   867  // Struct5 is a relatively large struct
   868  // with both integer and floating point values.
   869  type Struct5 struct {
   870  	A             uint16
   871  	B             int16
   872  	C, D          uint32
   873  	E             int32
   874  	F, G, H, I, J float32
   875  }
   876  
   877  // Struct6 has a nested struct.
   878  type Struct6 struct {
   879  	Struct1
   880  }
   881  
   882  // Struct7 is a struct with a nested array-typed field
   883  // that cannot be passed in registers as a result.
   884  type Struct7 struct {
   885  	Struct1
   886  	Struct2
   887  }
   888  
   889  // Struct8 is large aggregate struct type that may be
   890  // passed in registers.
   891  type Struct8 struct {
   892  	Struct5
   893  	Struct1
   894  }
   895  
   896  // Struct9 is a type that has an array type nested
   897  // 2 layers deep, and as a result needs to be passed
   898  // on the stack.
   899  type Struct9 struct {
   900  	Struct1
   901  	Struct7
   902  }
   903  
   904  // Struct10 is a struct type that is too large to be
   905  // passed in registers.
   906  type Struct10 struct {
   907  	Struct5
   908  	Struct8
   909  }
   910  
   911  // Struct11 is a struct type that has several reference
   912  // types in it.
   913  type Struct11 struct {
   914  	X map[string]int
   915  }
   916  
   917  // Struct12 has Struct11 embedded into it to test more
   918  // paths.
   919  type Struct12 struct {
   920  	A int
   921  	Struct11
   922  }
   923  
   924  // Struct13 tests an empty field.
   925  type Struct13 struct {
   926  	A int
   927  	X struct{}
   928  	B int
   929  }
   930  
   931  // Struct14 tests a non-zero-sized (and otherwise register-assignable)
   932  // struct with a field that is a non-zero length array with zero-sized members.
   933  type Struct14 struct {
   934  	A uintptr
   935  	X [3]struct{}
   936  	B float64
   937  }
   938  
   939  // Struct15 tests a non-zero-sized (and otherwise register-assignable)
   940  // struct with a struct field that is zero-sized but contains a
   941  // non-zero length array with zero-sized members.
   942  type Struct15 struct {
   943  	A uintptr
   944  	X struct {
   945  		Y [3]struct{}
   946  	}
   947  	B float64
   948  }
   949  
   950  const genValueRandSeed = 0
   951  
   952  // genValue generates a pseudorandom reflect.Value with type t.
   953  // The reflect.Value produced by this function is always the same
   954  // for the same type.
   955  func genValue(t *testing.T, typ reflect.Type, r *rand.Rand) reflect.Value {
   956  	// Re-seed and reset the PRNG because we want each value with the
   957  	// same type to be the same random value.
   958  	r.Seed(genValueRandSeed)
   959  	v, ok := quick.Value(typ, r)
   960  	if !ok {
   961  		t.Fatal("failed to generate value")
   962  	}
   963  	return v
   964  }
   965  
   966  func TestSignalingNaNArgument(t *testing.T) {
   967  	v := reflect.ValueOf(func(x float32) {
   968  		// make sure x is a signaling NaN.
   969  		u := math.Float32bits(x)
   970  		if u != snan {
   971  			t.Fatalf("signaling NaN not correct: %x\n", u)
   972  		}
   973  	})
   974  	v.Call([]reflect.Value{reflect.ValueOf(math.Float32frombits(snan))})
   975  }
   976  
   977  func TestSignalingNaNReturn(t *testing.T) {
   978  	v := reflect.ValueOf(func() float32 {
   979  		return math.Float32frombits(snan)
   980  	})
   981  	var x float32
   982  	reflect.ValueOf(&x).Elem().Set(v.Call(nil)[0])
   983  	// make sure x is a signaling NaN.
   984  	u := math.Float32bits(x)
   985  	if u != snan {
   986  		t.Fatalf("signaling NaN not correct: %x\n", u)
   987  	}
   988  }
   989  

View as plain text