]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/cmd/internal/obj/riscv/asm_test.go
cmd/internal/obj/riscv: fix the offset of JALR transformed from JAL
[gostls13.git] / src / cmd / internal / obj / riscv / asm_test.go
index b23142dbe8ecb503ff6c683b3f9c75496bf90bc7..afe0525532bba7a9d7cc3a26f4c77bcec755828f 100644 (file)
@@ -8,9 +8,7 @@ import (
        "bytes"
        "fmt"
        "internal/testenv"
-       "io/ioutil"
        "os"
-       "os/exec"
        "path/filepath"
        "runtime"
        "testing"
@@ -24,7 +22,7 @@ func TestLargeBranch(t *testing.T) {
        }
        testenv.MustHaveGoBuild(t)
 
-       dir, err := ioutil.TempDir("", "testlargebranch")
+       dir, err := os.MkdirTemp("", "testlargebranch")
        if err != nil {
                t.Fatalf("Could not create directory: %v", err)
        }
@@ -35,12 +33,12 @@ func TestLargeBranch(t *testing.T) {
        genLargeBranch(buf)
 
        tmpfile := filepath.Join(dir, "x.s")
-       if err := ioutil.WriteFile(tmpfile, buf.Bytes(), 0644); err != nil {
+       if err := os.WriteFile(tmpfile, buf.Bytes(), 0644); err != nil {
                t.Fatalf("Failed to write file: %v", err)
        }
 
        // Assemble generated file.
-       cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
+       cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
        cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
        out, err := cmd.CombinedOutput()
        if err != nil {
@@ -67,13 +65,13 @@ func TestLargeCall(t *testing.T) {
        }
        testenv.MustHaveGoBuild(t)
 
-       dir, err := ioutil.TempDir("", "testlargecall")
+       dir, err := os.MkdirTemp("", "testlargecall")
        if err != nil {
                t.Fatalf("could not create directory: %v", err)
        }
        defer os.RemoveAll(dir)
 
-       if err := ioutil.WriteFile(filepath.Join(dir, "go.mod"), []byte("module largecall"), 0644); err != nil {
+       if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module largecall"), 0644); err != nil {
                t.Fatalf("Failed to write file: %v\n", err)
        }
        main := `package main
@@ -84,7 +82,7 @@ func main() {
 func x()
 func y()
 `
-       if err := ioutil.WriteFile(filepath.Join(dir, "x.go"), []byte(main), 0644); err != nil {
+       if err := os.WriteFile(filepath.Join(dir, "x.go"), []byte(main), 0644); err != nil {
                t.Fatalf("failed to write main: %v\n", err)
        }
 
@@ -92,12 +90,12 @@ func y()
        buf := bytes.NewBuffer(make([]byte, 0, 7000000))
        genLargeCall(buf)
 
-       if err := ioutil.WriteFile(filepath.Join(dir, "x.s"), buf.Bytes(), 0644); err != nil {
+       if err := os.WriteFile(filepath.Join(dir, "x.s"), buf.Bytes(), 0644); err != nil {
                t.Fatalf("Failed to write file: %v\n", err)
        }
 
        // Build generated files.
-       cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-linkmode=internal")
+       cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-ldflags=-linkmode=internal")
        cmd.Dir = dir
        cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
        out, err := cmd.CombinedOutput()
@@ -106,7 +104,7 @@ func y()
        }
 
        if runtime.GOARCH == "riscv64" && testenv.HasCGO() {
-               cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-linkmode=external")
+               cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-ldflags=-linkmode=external")
                cmd.Dir = dir
                cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
                out, err := cmd.CombinedOutput()
@@ -128,18 +126,84 @@ func genLargeCall(buf *bytes.Buffer) {
        fmt.Fprintln(buf, "RET")
 }
 
+// TestLargeJump generates a large jump (>1MB of text) with a JMP to the
+// end of the function, in order to ensure that it assembles correctly.
+func TestLargeJump(t *testing.T) {
+       if testing.Short() {
+               t.Skip("Skipping test in short mode")
+       }
+       if runtime.GOARCH != "riscv64" {
+               t.Skip("Require riscv64 to run")
+       }
+       testenv.MustHaveGoBuild(t)
+
+       dir := t.TempDir()
+
+       if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module largejump"), 0644); err != nil {
+               t.Fatalf("Failed to write file: %v\n", err)
+       }
+       main := `package main
+
+import "fmt"
+
+func main() {
+        fmt.Print(x())
+}
+
+func x() uint64
+`
+       if err := os.WriteFile(filepath.Join(dir, "x.go"), []byte(main), 0644); err != nil {
+               t.Fatalf("failed to write main: %v\n", err)
+       }
+
+       // Generate a very large jump instruction.
+       buf := bytes.NewBuffer(make([]byte, 0, 7000000))
+       genLargeJump(buf)
+
+       if err := os.WriteFile(filepath.Join(dir, "x.s"), buf.Bytes(), 0644); err != nil {
+               t.Fatalf("Failed to write file: %v\n", err)
+       }
+
+       // Build generated files.
+       cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", "x.exe")
+       cmd.Dir = dir
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               t.Errorf("Build failed: %v, output: %s", err, out)
+       }
+
+       cmd = testenv.Command(t, filepath.Join(dir, "x.exe"))
+       out, err = cmd.CombinedOutput()
+       if string(out) != "1" {
+               t.Errorf(`Got test output %q, want "1"`, string(out))
+       }
+}
+
+func genLargeJump(buf *bytes.Buffer) {
+       fmt.Fprintln(buf, "TEXT ·x(SB),0,$0-8")
+       fmt.Fprintln(buf, "MOV  X0, X10")
+       fmt.Fprintln(buf, "JMP end")
+       for i := 0; i < 1<<18; i++ {
+               fmt.Fprintln(buf, "ADD $1, X10, X10")
+       }
+       fmt.Fprintln(buf, "end:")
+       fmt.Fprintln(buf, "ADD $1, X10, X10")
+       fmt.Fprintln(buf, "MOV X10, r+0(FP)")
+       fmt.Fprintln(buf, "RET")
+}
+
 // Issue 20348.
 func TestNoRet(t *testing.T) {
-       dir, err := ioutil.TempDir("", "testnoret")
+       dir, err := os.MkdirTemp("", "testnoret")
        if err != nil {
                t.Fatal(err)
        }
        defer os.RemoveAll(dir)
        tmpfile := filepath.Join(dir, "x.s")
-       if err := ioutil.WriteFile(tmpfile, []byte("TEXT ·stub(SB),$0-0\nNOP\n"), 0644); err != nil {
+       if err := os.WriteFile(tmpfile, []byte("TEXT ·stub(SB),$0-0\nNOP\n"), 0644); err != nil {
                t.Fatal(err)
        }
-       cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
+       cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
        cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
        if out, err := cmd.CombinedOutput(); err != nil {
                t.Errorf("%v\n%s", err, out)
@@ -147,7 +211,7 @@ func TestNoRet(t *testing.T) {
 }
 
 func TestImmediateSplitting(t *testing.T) {
-       dir, err := ioutil.TempDir("", "testimmsplit")
+       dir, err := os.MkdirTemp("", "testimmsplit")
        if err != nil {
                t.Fatal(err)
        }
@@ -190,10 +254,10 @@ TEXT _stub(SB),$0-0
        MOVF    F6, 4096(X5)
        MOVD    F6, 4096(X5)
 `
-       if err := ioutil.WriteFile(tmpfile, []byte(asm), 0644); err != nil {
+       if err := os.WriteFile(tmpfile, []byte(asm), 0644); err != nil {
                t.Fatal(err)
        }
-       cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
+       cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
        cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
        if out, err := cmd.CombinedOutput(); err != nil {
                t.Errorf("%v\n%s", err, out)
@@ -207,7 +271,7 @@ func TestBranch(t *testing.T) {
 
        testenv.MustHaveGoBuild(t)
 
-       cmd := exec.Command(testenv.GoToolPath(t), "test")
+       cmd := testenv.Command(t, testenv.GoToolPath(t), "test")
        cmd.Dir = "testdata/testbranch"
        if out, err := testenv.CleanCmdEnv(cmd).CombinedOutput(); err != nil {
                t.Errorf("Branch test failed: %v\n%s", err, out)