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