Source file test/live_regabi.go
1 // errorcheckwithauto -0 -l -live -wb=0 -d=ssa/insert_resched_checks/off 2 3 //go:build (amd64 && goexperiment.regabiargs) || (arm64 && goexperiment.regabiargs) 4 5 // Copyright 2014 The Go Authors. All rights reserved. 6 // Use of this source code is governed by a BSD-style 7 // license that can be found in the LICENSE file. 8 9 // liveness tests with inlining disabled. 10 // see also live2.go. 11 12 package main 13 14 import "runtime" 15 16 func printnl() 17 18 //go:noescape 19 func printpointer(**int) 20 21 //go:noescape 22 func printintpointer(*int) 23 24 //go:noescape 25 func printstringpointer(*string) 26 27 //go:noescape 28 func printstring(string) 29 30 //go:noescape 31 func printbytepointer(*byte) 32 33 func printint(int) 34 35 func f1() { 36 var x *int // ERROR "stack object x \*int$" 37 printpointer(&x) // ERROR "live at call to printpointer: x$" 38 printpointer(&x) 39 } 40 41 func f2(b bool) { 42 if b { 43 printint(0) // nothing live here 44 return 45 } 46 var x *int // ERROR "stack object x \*int$" 47 printpointer(&x) // ERROR "live at call to printpointer: x$" 48 printpointer(&x) 49 } 50 51 func f3(b1, b2 bool) { 52 // Here x and y are ambiguously live. In previous go versions they 53 // were marked as live throughout the function to avoid being 54 // poisoned in GODEBUG=gcdead=1 mode; this is now no longer the 55 // case. 56 57 printint(0) 58 if b1 == false { 59 printint(0) 60 return 61 } 62 63 if b2 { 64 var x *int // ERROR "stack object x \*int$" 65 printpointer(&x) // ERROR "live at call to printpointer: x$" 66 printpointer(&x) 67 } else { 68 var y *int // ERROR "stack object y \*int$" 69 printpointer(&y) // ERROR "live at call to printpointer: y$" 70 printpointer(&y) 71 } 72 printint(0) // nothing is live here 73 } 74 75 // The old algorithm treated x as live on all code that 76 // could flow to a return statement, so it included the 77 // function entry and code above the declaration of x 78 // but would not include an indirect use of x in an infinite loop. 79 // Check that these cases are handled correctly. 80 81 func f4(b1, b2 bool) { // x not live here 82 if b2 { 83 printint(0) // x not live here 84 return 85 } 86 var z **int 87 x := new(int) // ERROR "stack object x \*int$" 88 *x = 42 89 z = &x 90 printint(**z) // ERROR "live at call to printint: x$" 91 if b2 { 92 printint(1) // x not live here 93 return 94 } 95 for { 96 printint(**z) // ERROR "live at call to printint: x$" 97 } 98 } 99 100 func f5(b1 bool) { 101 var z **int 102 if b1 { 103 x := new(int) // ERROR "stack object x \*int$" 104 *x = 42 105 z = &x 106 } else { 107 y := new(int) // ERROR "stack object y \*int$" 108 *y = 54 109 z = &y 110 } 111 printint(**z) // nothing live here 112 } 113 114 // confusion about the _ result used to cause spurious "live at entry to f6: _". 115 116 func f6() (_, y string) { 117 y = "hello" 118 return 119 } 120 121 // confusion about addressed results used to cause "live at entry to f7: x". 122 123 func f7() (x string) { // ERROR "stack object x string" 124 _ = &x 125 x = "hello" 126 return 127 } 128 129 // ignoring block returns used to cause "live at entry to f8: x, y". 130 131 func f8() (x, y string) { 132 return g8() 133 } 134 135 func g8() (string, string) 136 137 // ignoring block assignments used to cause "live at entry to f9: x" 138 // issue 7205 139 140 var i9 interface{} 141 142 func f9() bool { 143 g8() 144 x := i9 145 y := interface{}(g18()) // ERROR "live at call to convT: x.data$" "live at call to g18: x.data$" "stack object .autotmp_[0-9]+ \[2\]string$" 146 i9 = y // make y escape so the line above has to call convT 147 return x != y 148 } 149 150 // liveness formerly confused by UNDEF followed by RET, 151 // leading to "live at entry to f10: ~r1" (unnamed result). 152 153 func f10() string { 154 panic(1) 155 } 156 157 // liveness formerly confused by select, thinking runtime.selectgo 158 // can return to next instruction; it always jumps elsewhere. 159 // note that you have to use at least two cases in the select 160 // to get a true select; smaller selects compile to optimized helper functions. 161 162 var c chan *int 163 var b bool 164 165 // this used to have a spurious "live at entry to f11a: ~r0" 166 func f11a() *int { 167 select { // ERROR "stack object .autotmp_[0-9]+ \[2\]runtime.scase$" 168 case <-c: 169 return nil 170 case <-c: 171 return nil 172 } 173 } 174 175 func f11b() *int { 176 p := new(int) 177 if b { 178 // At this point p is dead: the code here cannot 179 // get to the bottom of the function. 180 // This used to have a spurious "live at call to printint: p". 181 printint(1) // nothing live here! 182 select { // ERROR "stack object .autotmp_[0-9]+ \[2\]runtime.scase$" 183 case <-c: 184 return nil 185 case <-c: 186 return nil 187 } 188 } 189 println(*p) 190 return nil 191 } 192 193 var sink *int 194 195 func f11c() *int { 196 p := new(int) 197 sink = p // prevent stack allocation, otherwise p is rematerializeable 198 if b { 199 // Unlike previous, the cases in this select fall through, 200 // so we can get to the println, so p is not dead. 201 printint(1) // ERROR "live at call to printint: p$" 202 select { // ERROR "live at call to selectgo: p$" "stack object .autotmp_[0-9]+ \[2\]runtime.scase$" 203 case <-c: 204 case <-c: 205 } 206 } 207 println(*p) 208 return nil 209 } 210 211 // similarly, select{} does not fall through. 212 // this used to have a spurious "live at entry to f12: ~r0". 213 214 func f12() *int { 215 if b { 216 select {} 217 } else { 218 return nil 219 } 220 } 221 222 // incorrectly placed VARDEF annotations can cause missing liveness annotations. 223 // this used to be missing the fact that s is live during the call to g13 (because it is 224 // needed for the call to h13). 225 226 func f13() { 227 s := g14() 228 s = h13(s, g13(s)) // ERROR "live at call to g13: s.ptr$" 229 } 230 231 func g13(string) string 232 func h13(string, string) string 233 234 // more incorrectly placed VARDEF. 235 236 func f14() { 237 x := g14() // ERROR "stack object x string$" 238 printstringpointer(&x) 239 } 240 241 func g14() string 242 243 // Checking that various temporaries do not persist or cause 244 // ambiguously live values that must be zeroed. 245 // The exact temporary names are inconsequential but we are 246 // trying to check that there is only one at any given site, 247 // and also that none show up in "ambiguously live" messages. 248 249 var m map[string]int 250 var mi map[interface{}]int 251 252 // str and iface are used to ensure that a temp is required for runtime calls below. 253 func str() string 254 func iface() interface{} 255 256 func f16() { 257 if b { 258 delete(mi, iface()) // ERROR "stack object .autotmp_[0-9]+ interface \{\}$" 259 } 260 delete(mi, iface()) 261 delete(mi, iface()) 262 } 263 264 var m2s map[string]*byte 265 var m2 map[[2]string]*byte 266 var x2 [2]string 267 var bp *byte 268 269 func f17a(p *byte) { // ERROR "live at entry to f17a: p$" 270 if b { 271 m2[x2] = p // ERROR "live at call to mapassign: p$" 272 } 273 m2[x2] = p // ERROR "live at call to mapassign: p$" 274 m2[x2] = p // ERROR "live at call to mapassign: p$" 275 } 276 277 func f17b(p *byte) { // ERROR "live at entry to f17b: p$" 278 // key temporary 279 if b { 280 m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$" 281 } 282 m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$" 283 m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$" 284 } 285 286 func f17c() { 287 // key and value temporaries 288 if b { 289 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$" 290 } 291 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$" 292 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$" 293 } 294 295 func f17d() *byte 296 297 func g18() [2]string 298 299 func f18() { 300 // key temporary for mapaccess. 301 // temporary introduced by orderexpr. 302 var z *byte 303 if b { 304 z = m2[g18()] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" 305 } 306 z = m2[g18()] 307 z = m2[g18()] 308 printbytepointer(z) 309 } 310 311 var ch chan *byte 312 313 // byteptr is used to ensure that a temp is required for runtime calls below. 314 func byteptr() *byte 315 316 func f19() { 317 // dest temporary for channel receive. 318 var z *byte 319 320 if b { 321 z = <-ch // ERROR "stack object .autotmp_[0-9]+ \*byte$" 322 } 323 z = <-ch 324 z = <-ch // ERROR "live at call to chanrecv1: .autotmp_[0-9]+$" 325 printbytepointer(z) 326 } 327 328 func f20() { 329 // src temporary for channel send 330 if b { 331 ch <- byteptr() // ERROR "stack object .autotmp_[0-9]+ \*byte$" 332 } 333 ch <- byteptr() 334 ch <- byteptr() 335 } 336 337 func f21() { 338 // key temporary for mapaccess using array literal key. 339 var z *byte 340 if b { 341 z = m2[[2]string{"x", "y"}] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" 342 } 343 z = m2[[2]string{"x", "y"}] 344 z = m2[[2]string{"x", "y"}] 345 printbytepointer(z) 346 } 347 348 func f23() { 349 // key temporary for two-result map access using array literal key. 350 var z *byte 351 var ok bool 352 if b { 353 z, ok = m2[[2]string{"x", "y"}] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" 354 } 355 z, ok = m2[[2]string{"x", "y"}] 356 z, ok = m2[[2]string{"x", "y"}] 357 printbytepointer(z) 358 print(ok) 359 } 360 361 func f24() { 362 // key temporary for map access using array literal key. 363 // value temporary too. 364 if b { 365 m2[[2]string{"x", "y"}] = nil // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" 366 } 367 m2[[2]string{"x", "y"}] = nil 368 m2[[2]string{"x", "y"}] = nil 369 } 370 371 // Non-open-coded defers should not cause autotmps. (Open-coded defers do create extra autotmps). 372 func f25(b bool) { 373 for i := 0; i < 2; i++ { 374 // Put in loop to make sure defer is not open-coded 375 defer g25() 376 } 377 if b { 378 return 379 } 380 var x string 381 x = g14() 382 printstring(x) 383 return 384 } 385 386 func g25() 387 388 // non-escaping ... slices passed to function call should die on return, 389 // so that the temporaries do not stack and do not cause ambiguously 390 // live variables. 391 392 func f26(b bool) { 393 if b { 394 print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "stack object .autotmp_[0-9]+ \[3\]interface \{\}$" 395 } 396 print26((*int)(nil), (*int)(nil), (*int)(nil)) 397 print26((*int)(nil), (*int)(nil), (*int)(nil)) 398 printnl() 399 } 400 401 //go:noescape 402 func print26(...interface{}) 403 404 // non-escaping closures passed to function call should die on return 405 406 func f27(b bool) { 407 x := 0 408 if b { 409 call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{" 410 } 411 call27(func() { x++ }) 412 call27(func() { x++ }) 413 printnl() 414 } 415 416 // but defer does escape to later execution in the function 417 418 func f27defer(b bool) { 419 x := 0 420 if b { 421 defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{" 422 } 423 defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{" 424 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+ .autotmp_[0-9]+" 425 return // ERROR "live at indirect call: .autotmp_[0-9]+" 426 } 427 428 // and newproc (go) escapes to the heap 429 430 func f27go(b bool) { 431 x := 0 432 if b { 433 go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" "live at call to newobject: &x .autotmp_[0-9]+$" "live at call to newproc: &x$" // allocate two closures, the func literal, and the wrapper for go 434 } 435 go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" "live at call to newobject: .autotmp_[0-9]+$" // allocate two closures, the func literal, and the wrapper for go 436 printnl() 437 } 438 439 //go:noescape 440 func call27(func()) 441 442 // concatstring slice should die on return 443 444 var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string 445 446 func f28(b bool) { 447 if b { 448 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "stack object .autotmp_[0-9]+ \[10\]string$" 449 } 450 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) 451 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) 452 } 453 454 // map iterator should die on end of range loop 455 456 func f29(b bool) { 457 if b { 458 for k := range m { // ERROR "live at call to mapiterinit: .autotmp_[0-9]+$" "live at call to mapiternext: .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ runtime.hiter$" 459 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$" 460 } 461 } 462 for k := range m { // ERROR "live at call to mapiterinit: .autotmp_[0-9]+$" "live at call to mapiternext: .autotmp_[0-9]+$" 463 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$" 464 } 465 for k := range m { // ERROR "live at call to mapiterinit: .autotmp_[0-9]+$" "live at call to mapiternext: .autotmp_[0-9]+$" 466 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$" 467 } 468 } 469 470 // copy of array of pointers should die at end of range loop 471 var pstructarr [10]pstruct 472 473 // Struct size chosen to make pointer to element in pstructarr 474 // not computable by strength reduction. 475 type pstruct struct { 476 intp *int 477 _ [8]byte 478 } 479 480 func f30(b bool) { 481 // live temp during printintpointer(p): 482 // the internal iterator pointer if a pointer to pstruct in pstructarr 483 // can not be easily computed by strength reduction. 484 if b { 485 for _, p := range pstructarr { // ERROR "stack object .autotmp_[0-9]+ \[10\]pstruct$" 486 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$" 487 } 488 } 489 for _, p := range pstructarr { 490 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$" 491 } 492 for _, p := range pstructarr { 493 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$" 494 } 495 } 496 497 // conversion to interface should not leave temporary behind 498 499 func f31(b1, b2, b3 bool) { 500 if b1 { 501 g31(g18()) // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" 502 } 503 if b2 { 504 h31(g18()) // ERROR "live at call to convT: .autotmp_[0-9]+$" "live at call to newobject: .autotmp_[0-9]+$" 505 } 506 if b3 { 507 panic(g18()) 508 } 509 print(b3) 510 } 511 512 func g31(interface{}) 513 func h31(...interface{}) 514 515 // non-escaping partial functions passed to function call should die on return 516 517 type T32 int 518 519 func (t *T32) Inc() { // ERROR "live at entry to \(\*T32\).Inc: t$" 520 *t++ 521 } 522 523 var t32 T32 524 525 func f32(b bool) { 526 if b { 527 call32(t32.Inc) // ERROR "stack object .autotmp_[0-9]+ struct \{" 528 } 529 call32(t32.Inc) 530 call32(t32.Inc) 531 } 532 533 //go:noescape 534 func call32(func()) 535 536 // temporaries introduced during if conditions and && || expressions 537 // should die once the condition has been acted upon. 538 539 var m33 map[interface{}]int 540 541 func f33() { 542 if m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}$" 543 printnl() 544 return 545 } else { 546 printnl() 547 } 548 printnl() 549 } 550 551 func f34() { 552 if m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}$" 553 printnl() 554 return 555 } 556 printnl() 557 } 558 559 func f35() { 560 if m33[byteptr()] == 0 && // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 561 m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 562 printnl() 563 return 564 } 565 printnl() 566 } 567 568 func f36() { 569 if m33[byteptr()] == 0 || // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 570 m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 571 printnl() 572 return 573 } 574 printnl() 575 } 576 577 func f37() { 578 if (m33[byteptr()] == 0 || // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 579 m33[byteptr()] == 0) && // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 580 m33[byteptr()] == 0 { 581 printnl() 582 return 583 } 584 printnl() 585 } 586 587 // select temps should disappear in the case bodies 588 589 var c38 chan string 590 591 func fc38() chan string 592 func fi38(int) *string 593 func fb38() *bool 594 595 func f38(b bool) { 596 // we don't care what temps are printed on the lines with output. 597 // we care that the println lines have no live variables 598 // and therefore no output. 599 if b { 600 select { // ERROR "live at call to selectgo:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ \[4\]runtime.scase$" 601 case <-fc38(): 602 printnl() 603 case fc38() <- *fi38(1): // ERROR "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ string$" 604 printnl() 605 case *fi38(2) = <-fc38(): // ERROR "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ string$" 606 printnl() 607 case *fi38(3), *fb38() = <-fc38(): // ERROR "stack object .autotmp_[0-9]+ string$" "live at call to f[ibc]38:( .autotmp_[0-9]+)+$" 608 printnl() 609 } 610 printnl() 611 } 612 printnl() 613 } 614 615 // issue 8097: mishandling of x = x during return. 616 617 func f39() (x []int) { 618 x = []int{1} 619 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$" 620 return x 621 } 622 623 func f39a() (x []int) { 624 x = []int{1} 625 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$" 626 return 627 } 628 629 func f39b() (x [10]*int) { 630 x = [10]*int{} 631 x[0] = new(int) // ERROR "live at call to newobject: x$" 632 printnl() // ERROR "live at call to printnl: x$" 633 return x 634 } 635 636 func f39c() (x [10]*int) { 637 x = [10]*int{} 638 x[0] = new(int) // ERROR "live at call to newobject: x$" 639 printnl() // ERROR "live at call to printnl: x$" 640 return 641 } 642 643 // issue 8142: lost 'addrtaken' bit on inlined variables. 644 // no inlining in this test, so just checking that non-inlined works. 645 646 type T40 struct { 647 m map[int]int 648 } 649 650 //go:noescape 651 func useT40(*T40) 652 653 func newT40() *T40 { 654 ret := T40{} 655 ret.m = make(map[int]int, 42) // ERROR "live at call to makemap: &ret$" 656 return &ret 657 } 658 659 func bad40() { 660 t := newT40() 661 _ = t 662 printnl() 663 } 664 665 func good40() { 666 ret := T40{} // ERROR "stack object ret T40$" 667 ret.m = make(map[int]int) // ERROR "live at call to rand32: .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ runtime.hmap$" 668 t := &ret 669 printnl() // ERROR "live at call to printnl: ret$" 670 // Note: ret is live at the printnl because the compiler moves &ret 671 // from before the printnl to after. 672 useT40(t) 673 } 674 675 func ddd1(x, y *int) { // ERROR "live at entry to ddd1: x y$" 676 ddd2(x, y) // ERROR "stack object .autotmp_[0-9]+ \[2\]\*int$" 677 printnl() 678 // Note: no .?autotmp live at printnl. See issue 16996. 679 } 680 func ddd2(a ...*int) { // ERROR "live at entry to ddd2: a$" 681 sink = a[0] 682 } 683 684 // issue 16016: autogenerated wrapper should have arguments live 685 type T struct{} 686 687 func (*T) Foo(ptr *int) {} 688 689 type R struct{ *T } 690 691 // issue 18860: output arguments must be live all the time if there is a defer. 692 // In particular, at printint r must be live. 693 func f41(p, q *int) (r *int) { // ERROR "live at entry to f41: p q$" 694 r = p 695 defer func() { 696 recover() 697 }() 698 printint(0) // ERROR "live at call to printint: .autotmp_[0-9]+ q r$" 699 r = q 700 return // ERROR "live at call to f41.func1: .autotmp_[0-9]+ r$" 701 } 702 703 func f42() { 704 var p, q, r int 705 f43([]*int{&p, &q, &r}) // ERROR "stack object .autotmp_[0-9]+ \[3\]\*int$" 706 f43([]*int{&p, &r, &q}) 707 f43([]*int{&q, &p, &r}) 708 } 709 710 //go:noescape 711 func f43(a []*int) 712 713 // Assigning to a sub-element that makes up an entire local variable 714 // should clobber that variable. 715 func f44(f func() [2]*int) interface{} { // ERROR "live at entry to f44: f" 716 type T struct { 717 s [1][2]*int 718 } 719 ret := T{} // ERROR "stack object ret T" 720 ret.s[0] = f() 721 return ret 722 } 723 724 func f45(a, b, c, d, e, f, g, h, i, j, k, l *byte) { // ERROR "live at entry to f45: a b c d e f g h i j k l" 725 f46(a, b, c, d, e, f, g, h, i, j, k, l) // ERROR "live at call to f46: a b c d e f g h i j k l" 726 runtime.KeepAlive(a) 727 runtime.KeepAlive(b) 728 runtime.KeepAlive(c) 729 runtime.KeepAlive(d) 730 runtime.KeepAlive(e) 731 runtime.KeepAlive(f) 732 runtime.KeepAlive(g) 733 runtime.KeepAlive(h) 734 runtime.KeepAlive(i) 735 runtime.KeepAlive(j) 736 runtime.KeepAlive(k) 737 runtime.KeepAlive(l) 738 } 739 740 //go:noinline 741 func f46(a, b, c, d, e, f, g, h, i, j, k, l *byte) { 742 } 743