1// run 2 3//go:build !nacl && !js && !wasip1 && !gccgo 4 5// Copyright 2019 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// Test that the linker permits long call sequences. 10package main 11 12import ( 13 "bytes" 14 "fmt" 15 "io/ioutil" 16 "os" 17 "os/exec" 18 "path/filepath" 19 "strconv" 20) 21 22const start = ` 23package main 24 25func main() { 26 println(f0() + 1) 27} 28` 29 30const fn = ` 31//go:noinline 32func f%d() int { 33 return f%d() + 1 34}` 35 36const fnlast = ` 37//go:noinline 38func f%d() int { 39 return 0 40} 41` 42 43const count = 400 44 45func main() { 46 if err := test(); err != nil { 47 fmt.Fprintln(os.Stderr, err) 48 os.Exit(1) 49 } 50} 51 52func test() error { 53 var buf bytes.Buffer 54 buf.WriteString(start) 55 for i := 0; i < count; i++ { 56 fmt.Fprintf(&buf, fn, i, i + 1) 57 } 58 fmt.Fprintf(&buf, fnlast, count) 59 60 dir, err := ioutil.TempDir("", "issue33555") 61 if err != nil { 62 return err 63 } 64 defer os.RemoveAll(dir) 65 66 fn := filepath.Join(dir, "x.go") 67 if err := ioutil.WriteFile(fn, buf.Bytes(), 0644); err != nil { 68 return err 69 } 70 71 out, err := exec.Command("go", "run", fn).CombinedOutput() 72 if err != nil { 73 return err 74 } 75 76 want := strconv.Itoa(count + 1) 77 if got := string(bytes.TrimSpace(out)); got != want { 78 return fmt.Errorf("got %q want %q", got, want) 79 } 80 81 return nil 82} 83