@@ -126,6 +126,72 @@ func genLargeCall(buf *bytes.Buffer) {
126126 fmt .Fprintln (buf , "RET" )
127127}
128128
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 ) {
132+ if testing .Short () {
133+ t .Skip ("Skipping test in short mode" )
134+ }
135+ if runtime .GOARCH != "riscv64" {
136+ t .Skip ("Require riscv64 to run" )
137+ }
138+ testenv .MustHaveGoBuild (t )
139+
140+ dir := t .TempDir ()
141+
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 )
144+ }
145+ main := `package main
146+
147+ import "fmt"
148+
149+ func main() {
150+ fmt.Print(x())
151+ }
152+
153+ func x() uint64
154+ `
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 )
157+ }
158+
159+ // Generate a very large jump instruction.
160+ buf := bytes .NewBuffer (make ([]byte , 0 , 7000000 ))
161+ genLargeJump (buf )
162+
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 )
165+ }
166+
167+ // Build generated files.
168+ cmd := testenv .Command (t , testenv .GoToolPath (t ), "build" , "-o" , "x.exe" )
169+ cmd .Dir = dir
170+ out , err := cmd .CombinedOutput ()
171+ if err != nil {
172+ t .Errorf ("Build failed: %v, output: %s" , err , out )
173+ }
174+
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 ))
179+ }
180+ }
181+
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" )
188+ }
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" )
193+ }
194+
129195// Issue 20348.
130196func TestNoRet (t * testing.T ) {
131197 dir , err := os .MkdirTemp ("" , "testnoret" )
0 commit comments