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.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  //
   549  //go:registerparams
   550  //go:noinline
   551  func passStruct10AndSmall(a Struct10, b byte, c uint) (Struct10, byte, uint) {
   552  	return a, b, c
   553  }
   554  
   555  var 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
   603  func callArgsNone(f func(MagicLastTypeNameForTestingRegisterABI)) {
   604  	f(MagicLastTypeNameForTestingRegisterABI{})
   605  }
   606  
   607  //go:registerparams
   608  //go:noinline
   609  func callArgsInt(f func(int, MagicLastTypeNameForTestingRegisterABI) int, a0 int) int {
   610  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   611  }
   612  
   613  //go:registerparams
   614  //go:noinline
   615  func callArgsInt8(f func(int8, MagicLastTypeNameForTestingRegisterABI) int8, a0 int8) int8 {
   616  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   617  }
   618  
   619  //go:registerparams
   620  //go:noinline
   621  func callArgsInt16(f func(int16, MagicLastTypeNameForTestingRegisterABI) int16, a0 int16) int16 {
   622  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   623  }
   624  
   625  //go:registerparams
   626  //go:noinline
   627  func callArgsInt32(f func(int32, MagicLastTypeNameForTestingRegisterABI) int32, a0 int32) int32 {
   628  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   629  }
   630  
   631  //go:registerparams
   632  //go:noinline
   633  func callArgsInt64(f func(int64, MagicLastTypeNameForTestingRegisterABI) int64, a0 int64) int64 {
   634  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   635  }
   636  
   637  //go:registerparams
   638  //go:noinline
   639  func callArgsUint(f func(uint, MagicLastTypeNameForTestingRegisterABI) uint, a0 uint) uint {
   640  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   641  }
   642  
   643  //go:registerparams
   644  //go:noinline
   645  func callArgsUint8(f func(uint8, MagicLastTypeNameForTestingRegisterABI) uint8, a0 uint8) uint8 {
   646  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   647  }
   648  
   649  //go:registerparams
   650  //go:noinline
   651  func callArgsUint16(f func(uint16, MagicLastTypeNameForTestingRegisterABI) uint16, a0 uint16) uint16 {
   652  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   653  }
   654  
   655  //go:registerparams
   656  //go:noinline
   657  func callArgsUint32(f func(uint32, MagicLastTypeNameForTestingRegisterABI) uint32, a0 uint32) uint32 {
   658  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   659  }
   660  
   661  //go:registerparams
   662  //go:noinline
   663  func callArgsUint64(f func(uint64, MagicLastTypeNameForTestingRegisterABI) uint64, a0 uint64) uint64 {
   664  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   665  }
   666  
   667  //go:registerparams
   668  //go:noinline
   669  func callArgsFloat32(f func(float32, MagicLastTypeNameForTestingRegisterABI) float32, a0 float32) float32 {
   670  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   671  }
   672  
   673  //go:registerparams
   674  //go:noinline
   675  func callArgsFloat64(f func(float64, MagicLastTypeNameForTestingRegisterABI) float64, a0 float64) float64 {
   676  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   677  }
   678  
   679  //go:registerparams
   680  //go:noinline
   681  func callArgsComplex64(f func(complex64, MagicLastTypeNameForTestingRegisterABI) complex64, a0 complex64) complex64 {
   682  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   683  }
   684  
   685  //go:registerparams
   686  //go:noinline
   687  func callArgsComplex128(f func(complex128, MagicLastTypeNameForTestingRegisterABI) complex128, a0 complex128) complex128 {
   688  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   689  }
   690  
   691  //go:registerparams
   692  //go:noinline
   693  func 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
   699  func 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
   705  func 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
   711  func callArgsString(f func(string, MagicLastTypeNameForTestingRegisterABI) string, a0 string) string {
   712  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   713  }
   714  
   715  //go:registerparams
   716  //go:noinline
   717  func callArgsSlice(f func([]byte, MagicLastTypeNameForTestingRegisterABI) []byte, a0 []byte) []byte {
   718  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   719  }
   720  
   721  //go:registerparams
   722  //go:noinline
   723  func callArgsPointer(f func(*byte, MagicLastTypeNameForTestingRegisterABI) *byte, a0 *byte) *byte {
   724  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   725  }
   726  
   727  //go:registerparams
   728  //go:noinline
   729  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) {
   730  	return f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, MagicLastTypeNameForTestingRegisterABI{})
   731  }
   732  
   733  //go:registerparams
   734  //go:noinline
   735  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) {
   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
   741  func callArgsStruct1(f func(Struct1, MagicLastTypeNameForTestingRegisterABI) Struct1, a0 Struct1) Struct1 {
   742  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   743  }
   744  
   745  //go:registerparams
   746  //go:noinline
   747  func callArgsStruct2(f func(Struct2, MagicLastTypeNameForTestingRegisterABI) Struct2, a0 Struct2) Struct2 {
   748  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   749  }
   750  
   751  //go:registerparams
   752  //go:noinline
   753  func callArgsStruct3(f func(Struct3, MagicLastTypeNameForTestingRegisterABI) Struct3, a0 Struct3) Struct3 {
   754  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   755  }
   756  
   757  //go:registerparams
   758  //go:noinline
   759  func callArgsStruct4(f func(Struct4, MagicLastTypeNameForTestingRegisterABI) Struct4, a0 Struct4) Struct4 {
   760  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   761  }
   762  
   763  //go:registerparams
   764  //go:noinline
   765  func callArgsStruct5(f func(Struct5, MagicLastTypeNameForTestingRegisterABI) Struct5, a0 Struct5) Struct5 {
   766  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   767  }
   768  
   769  //go:registerparams
   770  //go:noinline
   771  func callArgsStruct6(f func(Struct6, MagicLastTypeNameForTestingRegisterABI) Struct6, a0 Struct6) Struct6 {
   772  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   773  }
   774  
   775  //go:registerparams
   776  //go:noinline
   777  func callArgsStruct7(f func(Struct7, MagicLastTypeNameForTestingRegisterABI) Struct7, a0 Struct7) Struct7 {
   778  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   779  }
   780  
   781  //go:registerparams
   782  //go:noinline
   783  func callArgsStruct8(f func(Struct8, MagicLastTypeNameForTestingRegisterABI) Struct8, a0 Struct8) Struct8 {
   784  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   785  }
   786  
   787  //go:registerparams
   788  //go:noinline
   789  func callArgsStruct9(f func(Struct9, MagicLastTypeNameForTestingRegisterABI) Struct9, a0 Struct9) Struct9 {
   790  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   791  }
   792  
   793  //go:registerparams
   794  //go:noinline
   795  func callArgsStruct10(f func(Struct10, MagicLastTypeNameForTestingRegisterABI) Struct10, a0 Struct10) Struct10 {
   796  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   797  }
   798  
   799  //go:registerparams
   800  //go:noinline
   801  func callArgsStruct11(f func(Struct11, MagicLastTypeNameForTestingRegisterABI) Struct11, a0 Struct11) Struct11 {
   802  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   803  }
   804  
   805  //go:registerparams
   806  //go:noinline
   807  func callArgsStruct12(f func(Struct12, MagicLastTypeNameForTestingRegisterABI) Struct12, a0 Struct12) Struct12 {
   808  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   809  }
   810  
   811  //go:registerparams
   812  //go:noinline
   813  func callArgsStruct13(f func(Struct13, MagicLastTypeNameForTestingRegisterABI) Struct13, a0 Struct13) Struct13 {
   814  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   815  }
   816  
   817  //go:registerparams
   818  //go:noinline
   819  func callArgsStruct14(f func(Struct14, MagicLastTypeNameForTestingRegisterABI) Struct14, a0 Struct14) Struct14 {
   820  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   821  }
   822  
   823  //go:registerparams
   824  //go:noinline
   825  func callArgsStruct15(f func(Struct15, MagicLastTypeNameForTestingRegisterABI) Struct15, a0 Struct15) Struct15 {
   826  	return f(a0, MagicLastTypeNameForTestingRegisterABI{})
   827  }
   828  
   829  //go:registerparams
   830  //go:noinline
   831  func 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
   837  func 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.
   842  type 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.
   848  type 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.
   855  type 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.
   862  type 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.
   870  type 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.
   879  type 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.
   885  type Struct7 struct {
   886  	Struct1
   887  	Struct2
   888  }
   889  
   890  // Struct8 is large aggregate struct type that may be
   891  // passed in registers.
   892  type 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.
   900  type Struct9 struct {
   901  	Struct1
   902  	Struct7
   903  }
   904  
   905  // Struct10 is a struct type that is too large to be
   906  // passed in registers.
   907  type Struct10 struct {
   908  	Struct5
   909  	Struct8
   910  }
   911  
   912  // Struct11 is a struct type that has several reference
   913  // types in it.
   914  type Struct11 struct {
   915  	X map[string]int
   916  }
   917  
   918  // Struct12 has Struct11 embedded into it to test more
   919  // paths.
   920  type Struct12 struct {
   921  	A int
   922  	Struct11
   923  }
   924  
   925  // Struct13 tests an empty field.
   926  type 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.
   934  type 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.
   943  type Struct15 struct {
   944  	A uintptr
   945  	X struct {
   946  		Y [3]struct{}
   947  	}
   948  	B float64
   949  }
   950  
   951  const 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.
   956  func 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  
   967  func 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  
   978  func 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  

View as plain text