github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/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.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 }