Skip to content

Commit 7cab55d

Browse files
committed
cmd/internal/obj/riscv: handle call, jmp and branch
Also provide REG_LR to more clearly define the link register. Based on the riscv-go port. Updates golang#27532 Change-Id: I0805f373682f93b3918a01c21d4ef34eb3817c75 Reviewed-on: https://go-review.googlesource.com/c/go/+/204627 Reviewed-by: Cherry Zhang <cherryyz@google.com> Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
1 parent 372efbb commit 7cab55d

File tree

4 files changed

+331
-2
lines changed

4 files changed

+331
-2
lines changed

src/cmd/asm/internal/asm/testdata/riscvenc.s

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,18 @@ start:
267267
MOVD 4(X5), F0 // 07b04200
268268
MOVD F0, 4(X5) // 27b20200
269269
MOVD F0, F1 // d3000022
270+
271+
// These jumps can get printed as jumps to 2 because they go to the
272+
// second instruction in the function (the first instruction is an
273+
// invisible stack pointer adjustment).
274+
JMP start // JMP 2 // 6ff05fcd
275+
JMP (X5) // 67800200
276+
JMP 4(X5) // 67804200
277+
278+
// JMP and CALL to symbol are encoded as:
279+
// AUIPC $0, TMP
280+
// JALR $0, TMP
281+
// with a R_RISCV_PCREL_ITYPE relocation - the linker resolves the
282+
// real address and updates the immediates for both instructions.
283+
CALL asmtest(SB) // 970f0000
284+
JMP asmtest(SB) // 970f0000
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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+
"io/ioutil"
12+
"os"
13+
"os/exec"
14+
"path/filepath"
15+
"testing"
16+
)
17+
18+
// TestLarge generates a very large file to verify that large
19+
// program builds successfully, in particular, too-far
20+
// conditional branches are fixed.
21+
func TestLarge(t *testing.T) {
22+
if testing.Short() {
23+
t.Skip("Skip in short mode")
24+
}
25+
testenv.MustHaveGoBuild(t)
26+
27+
dir, err := ioutil.TempDir("", "testlarge")
28+
if err != nil {
29+
t.Fatalf("could not create directory: %v", err)
30+
}
31+
defer os.RemoveAll(dir)
32+
33+
// Generate a very large function.
34+
buf := bytes.NewBuffer(make([]byte, 0, 7000000))
35+
gen(buf)
36+
37+
tmpfile := filepath.Join(dir, "x.s")
38+
err = ioutil.WriteFile(tmpfile, buf.Bytes(), 0644)
39+
if err != nil {
40+
t.Fatalf("can't write output: %v\n", err)
41+
}
42+
43+
// Build generated file.
44+
cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
45+
cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
46+
out, err := cmd.CombinedOutput()
47+
if err != nil {
48+
t.Errorf("Build failed: %v, output: %s", err, out)
49+
}
50+
}
51+
52+
// gen generates a very large program, with a very far conditional branch.
53+
func gen(buf *bytes.Buffer) {
54+
fmt.Fprintln(buf, "TEXT f(SB),0,$0-0")
55+
fmt.Fprintln(buf, "BEQ X0, X0, label")
56+
for i := 0; i < 1<<19; i++ {
57+
fmt.Fprintln(buf, "ADD $0, X0, X0")
58+
}
59+
fmt.Fprintln(buf, "label:")
60+
fmt.Fprintln(buf, "ADD $0, X0, X0")
61+
}
62+
63+
// Issue 20348.
64+
func TestNoRet(t *testing.T) {
65+
dir, err := ioutil.TempDir("", "testnoret")
66+
if err != nil {
67+
t.Fatal(err)
68+
}
69+
defer os.RemoveAll(dir)
70+
tmpfile := filepath.Join(dir, "x.s")
71+
if err := ioutil.WriteFile(tmpfile, []byte("TEXT ·stub(SB),$0-0\nNOP\n"), 0644); err != nil {
72+
t.Fatal(err)
73+
}
74+
cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
75+
cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
76+
if out, err := cmd.CombinedOutput(); err != nil {
77+
t.Errorf("%v\n%s", err, out)
78+
}
79+
}

src/cmd/internal/obj/riscv/cpu.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ const (
141141
// Go runtime register names.
142142
REG_G = REG_TP // G pointer.
143143
REG_CTXT = REG_S4 // Context for closures.
144+
REG_LR = REG_RA // Link register.
144145
REG_TMP = REG_T6 // Reserved for assembler use.
145146

146147
// ABI names for floating point registers.

0 commit comments

Comments
 (0)