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