1 // Copyright 2019 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.
17 // TestLargeBranch generates a large function with a very far conditional
18 // branch, in order to ensure that it assembles successfully.
19 func TestLargeBranch(t *testing.T) {
21 t.Skip("Skipping test in short mode")
23 testenv.MustHaveGoBuild(t)
25 dir, err := os.MkdirTemp("", "testlargebranch")
27 t.Fatalf("Could not create directory: %v", err)
29 defer os.RemoveAll(dir)
31 // Generate a very large function.
32 buf := bytes.NewBuffer(make([]byte, 0, 7000000))
35 tmpfile := filepath.Join(dir, "x.s")
36 if err := os.WriteFile(tmpfile, buf.Bytes(), 0644); err != nil {
37 t.Fatalf("Failed to write file: %v", err)
40 // Assemble generated file.
41 cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
42 cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
43 out, err := cmd.CombinedOutput()
45 t.Errorf("Build failed: %v, output: %s", err, out)
49 func genLargeBranch(buf *bytes.Buffer) {
50 fmt.Fprintln(buf, "TEXT f(SB),0,$0-0")
51 fmt.Fprintln(buf, "BEQ X0, X0, label")
52 for i := 0; i < 1<<19; i++ {
53 fmt.Fprintln(buf, "ADD $0, X0, X0")
55 fmt.Fprintln(buf, "label:")
56 fmt.Fprintln(buf, "ADD $0, X0, X0")
59 // TestLargeCall generates a large function (>1MB of text) with a call to
60 // a following function, in order to ensure that it assembles and links
62 func TestLargeCall(t *testing.T) {
64 t.Skip("Skipping test in short mode")
66 testenv.MustHaveGoBuild(t)
68 dir, err := os.MkdirTemp("", "testlargecall")
70 t.Fatalf("could not create directory: %v", err)
72 defer os.RemoveAll(dir)
74 if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module largecall"), 0644); err != nil {
75 t.Fatalf("Failed to write file: %v\n", err)
85 if err := os.WriteFile(filepath.Join(dir, "x.go"), []byte(main), 0644); err != nil {
86 t.Fatalf("failed to write main: %v\n", err)
89 // Generate a very large function with call.
90 buf := bytes.NewBuffer(make([]byte, 0, 7000000))
93 if err := os.WriteFile(filepath.Join(dir, "x.s"), buf.Bytes(), 0644); err != nil {
94 t.Fatalf("Failed to write file: %v\n", err)
97 // Build generated files.
98 cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-ldflags=-linkmode=internal")
100 cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
101 out, err := cmd.CombinedOutput()
103 t.Errorf("Build failed: %v, output: %s", err, out)
106 if runtime.GOARCH == "riscv64" && testenv.HasCGO() {
107 cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-ldflags=-linkmode=external")
109 cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
110 out, err := cmd.CombinedOutput()
112 t.Errorf("Build failed: %v, output: %s", err, out)
117 func genLargeCall(buf *bytes.Buffer) {
118 fmt.Fprintln(buf, "TEXT ·x(SB),0,$0-0")
119 fmt.Fprintln(buf, "CALL ·y(SB)")
120 for i := 0; i < 1<<19; i++ {
121 fmt.Fprintln(buf, "ADD $0, X0, X0")
123 fmt.Fprintln(buf, "RET")
124 fmt.Fprintln(buf, "TEXT ·y(SB),0,$0-0")
125 fmt.Fprintln(buf, "ADD $0, X0, X0")
126 fmt.Fprintln(buf, "RET")
129 // TestLargeJump generates a large jump (>1MB of text) with a JMP to the
130 // end of the function, in order to ensure that it assembles correctly.
131 func TestLargeJump(t *testing.T) {
133 t.Skip("Skipping test in short mode")
135 if runtime.GOARCH != "riscv64" {
136 t.Skip("Require riscv64 to run")
138 testenv.MustHaveGoBuild(t)
142 if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module largejump"), 0644); err != nil {
143 t.Fatalf("Failed to write file: %v\n", err)
145 main := `package main
155 if err := os.WriteFile(filepath.Join(dir, "x.go"), []byte(main), 0644); err != nil {
156 t.Fatalf("failed to write main: %v\n", err)
159 // Generate a very large jump instruction.
160 buf := bytes.NewBuffer(make([]byte, 0, 7000000))
163 if err := os.WriteFile(filepath.Join(dir, "x.s"), buf.Bytes(), 0644); err != nil {
164 t.Fatalf("Failed to write file: %v\n", err)
167 // Build generated files.
168 cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", "x.exe")
170 out, err := cmd.CombinedOutput()
172 t.Errorf("Build failed: %v, output: %s", err, out)
175 cmd = testenv.Command(t, filepath.Join(dir, "x.exe"))
176 out, err = cmd.CombinedOutput()
177 if string(out) != "1" {
178 t.Errorf(`Got test output %q, want "1"`, string(out))
182 func genLargeJump(buf *bytes.Buffer) {
183 fmt.Fprintln(buf, "TEXT ·x(SB),0,$0-8")
184 fmt.Fprintln(buf, "MOV X0, X10")
185 fmt.Fprintln(buf, "JMP end")
186 for i := 0; i < 1<<18; i++ {
187 fmt.Fprintln(buf, "ADD $1, X10, X10")
189 fmt.Fprintln(buf, "end:")
190 fmt.Fprintln(buf, "ADD $1, X10, X10")
191 fmt.Fprintln(buf, "MOV X10, r+0(FP)")
192 fmt.Fprintln(buf, "RET")
196 func TestNoRet(t *testing.T) {
197 dir, err := os.MkdirTemp("", "testnoret")
201 defer os.RemoveAll(dir)
202 tmpfile := filepath.Join(dir, "x.s")
203 if err := os.WriteFile(tmpfile, []byte("TEXT ·stub(SB),$0-0\nNOP\n"), 0644); err != nil {
206 cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
207 cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
208 if out, err := cmd.CombinedOutput(); err != nil {
209 t.Errorf("%v\n%s", err, out)
213 func TestImmediateSplitting(t *testing.T) {
214 dir, err := os.MkdirTemp("", "testimmsplit")
218 defer os.RemoveAll(dir)
219 tmpfile := filepath.Join(dir, "x.s")
257 if err := os.WriteFile(tmpfile, []byte(asm), 0644); err != nil {
260 cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
261 cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
262 if out, err := cmd.CombinedOutput(); err != nil {
263 t.Errorf("%v\n%s", err, out)
267 func TestBranch(t *testing.T) {
268 if runtime.GOARCH != "riscv64" {
269 t.Skip("Requires riscv64 to run")
272 testenv.MustHaveGoBuild(t)
274 cmd := testenv.Command(t, testenv.GoToolPath(t), "test")
275 cmd.Dir = "testdata/testbranch"
276 if out, err := testenv.CleanCmdEnv(cmd).CombinedOutput(); err != nil {
277 t.Errorf("Branch test failed: %v\n%s", err, out)