github.com/m10x/go/src@v0.0.0-20220112094212-ba61592315da/reflect/abi_test.go (about) 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 }