]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/internal/obj/riscv/asm_test.go
c22428cdc5b816ee3a6dc71dbd5e2c4af261a04a
[gostls13.git] / src / cmd / internal / obj / riscv / asm_test.go
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.
4
5 package riscv
6
7 import (
8         "bytes"
9         "fmt"
10         "internal/testenv"
11         "os"
12         "path/filepath"
13         "runtime"
14         "testing"
15 )
16
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) {
20         if testing.Short() {
21                 t.Skip("Skipping test in short mode")
22         }
23         testenv.MustHaveGoBuild(t)
24
25         dir, err := os.MkdirTemp("", "testlargebranch")
26         if err != nil {
27                 t.Fatalf("Could not create directory: %v", err)
28         }
29         defer os.RemoveAll(dir)
30
31         // Generate a very large function.
32         buf := bytes.NewBuffer(make([]byte, 0, 7000000))
33         genLargeBranch(buf)
34
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)
38         }
39
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()
44         if err != nil {
45                 t.Errorf("Build failed: %v, output: %s", err, out)
46         }
47 }
48
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")
54         }
55         fmt.Fprintln(buf, "label:")
56         fmt.Fprintln(buf, "ADD $0, X0, X0")
57 }
58
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
61 // correctly.
62 func TestLargeCall(t *testing.T) {
63         if testing.Short() {
64                 t.Skip("Skipping test in short mode")
65         }
66         testenv.MustHaveGoBuild(t)
67
68         dir, err := os.MkdirTemp("", "testlargecall")
69         if err != nil {
70                 t.Fatalf("could not create directory: %v", err)
71         }
72         defer os.RemoveAll(dir)
73
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)
76         }
77         main := `package main
78 func main() {
79         x()
80 }
81
82 func x()
83 func y()
84 `
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)
87         }
88
89         // Generate a very large function with call.
90         buf := bytes.NewBuffer(make([]byte, 0, 7000000))
91         genLargeCall(buf)
92
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)
95         }
96
97         // Build generated files.
98         cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-ldflags=-linkmode=internal")
99         cmd.Dir = dir
100         cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
101         out, err := cmd.CombinedOutput()
102         if err != nil {
103                 t.Errorf("Build failed: %v, output: %s", err, out)
104         }
105
106         if runtime.GOARCH == "riscv64" && testenv.HasCGO() {
107                 cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-ldflags=-linkmode=external")
108                 cmd.Dir = dir
109                 cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
110                 out, err := cmd.CombinedOutput()
111                 if err != nil {
112                         t.Errorf("Build failed: %v, output: %s", err, out)
113                 }
114         }
115 }
116
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")
122         }
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")
127 }
128
129 // Issue 20348.
130 func TestNoRet(t *testing.T) {
131         dir, err := os.MkdirTemp("", "testnoret")
132         if err != nil {
133                 t.Fatal(err)
134         }
135         defer os.RemoveAll(dir)
136         tmpfile := filepath.Join(dir, "x.s")
137         if err := os.WriteFile(tmpfile, []byte("TEXT ·stub(SB),$0-0\nNOP\n"), 0644); err != nil {
138                 t.Fatal(err)
139         }
140         cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
141         cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
142         if out, err := cmd.CombinedOutput(); err != nil {
143                 t.Errorf("%v\n%s", err, out)
144         }
145 }
146
147 func TestImmediateSplitting(t *testing.T) {
148         dir, err := os.MkdirTemp("", "testimmsplit")
149         if err != nil {
150                 t.Fatal(err)
151         }
152         defer os.RemoveAll(dir)
153         tmpfile := filepath.Join(dir, "x.s")
154         asm := `
155 TEXT _stub(SB),$0-0
156         LB      4096(X5), X6
157         LH      4096(X5), X6
158         LW      4096(X5), X6
159         LD      4096(X5), X6
160         LBU     4096(X5), X6
161         LHU     4096(X5), X6
162         LWU     4096(X5), X6
163         SB      X6, 4096(X5)
164         SH      X6, 4096(X5)
165         SW      X6, 4096(X5)
166         SD      X6, 4096(X5)
167
168         FLW     4096(X5), F6
169         FLD     4096(X5), F6
170         FSW     F6, 4096(X5)
171         FSD     F6, 4096(X5)
172
173         MOVB    4096(X5), X6
174         MOVH    4096(X5), X6
175         MOVW    4096(X5), X6
176         MOV     4096(X5), X6
177         MOVBU   4096(X5), X6
178         MOVHU   4096(X5), X6
179         MOVWU   4096(X5), X6
180
181         MOVB    X6, 4096(X5)
182         MOVH    X6, 4096(X5)
183         MOVW    X6, 4096(X5)
184         MOV     X6, 4096(X5)
185
186         MOVF    4096(X5), F6
187         MOVD    4096(X5), F6
188         MOVF    F6, 4096(X5)
189         MOVD    F6, 4096(X5)
190 `
191         if err := os.WriteFile(tmpfile, []byte(asm), 0644); err != nil {
192                 t.Fatal(err)
193         }
194         cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
195         cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
196         if out, err := cmd.CombinedOutput(); err != nil {
197                 t.Errorf("%v\n%s", err, out)
198         }
199 }
200
201 func TestBranch(t *testing.T) {
202         if runtime.GOARCH != "riscv64" {
203                 t.Skip("Requires riscv64 to run")
204         }
205
206         testenv.MustHaveGoBuild(t)
207
208         cmd := testenv.Command(t, testenv.GoToolPath(t), "test")
209         cmd.Dir = "testdata/testbranch"
210         if out, err := testenv.CleanCmdEnv(cmd).CombinedOutput(); err != nil {
211                 t.Errorf("Branch test failed: %v\n%s", err, out)
212         }
213 }