aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj
diff options
context:
space:
mode:
authorCherry Mui <cherryyz@google.com>2025-11-24 11:03:06 -0500
committerCherry Mui <cherryyz@google.com>2025-11-24 11:03:06 -0500
commit220d73cc44a0c580dc8ee10df6395c8e517e118f (patch)
treed072aab20229f5489f43a0ce13ab52ff867ba38c /src/cmd/internal/obj
parent0c69e7734308f36de7acbeda4cabced8018c04e3 (diff)
parent8dd5b13abcb64993959ea02c3f664654af6367a9 (diff)
downloadgo-220d73cc44a0c580dc8ee10df6395c8e517e118f.tar.xz
[dev.simd] all: merge master (8dd5b13) into dev.simd
Merge List: + 2025-11-24 8dd5b13abc cmd/compile: relax stmtline_test on amd64 + 2025-11-23 feae743bdb cmd/compile: use 32x32->64 multiplies on loong64 + 2025-11-23 e88be8a128 runtime: fix stale comment for mheap/malloc + 2025-11-23 a318843a2a cmd/internal/obj/loong64: optimize duplicate optab entries + 2025-11-23 a18294bb6a cmd/internal/obj/arm64, image/gif, runtime, sort: use math/bits to calculate log2 + 2025-11-23 437323ef7b slices: fix incorrect comment in slices.Insert function documentation + 2025-11-23 1993dca400 doc/next: pre-announce end of support for macOS 12 in Go 1.27 + 2025-11-22 337f7b1f5d cmd/go: update default go directive in mod or work init + 2025-11-21 3c26aef8fb cmd/internal/obj/riscv: improve large branch/call/jump tests + 2025-11-21 31aa9f800b crypto/tls: use inner hello for earlyData when using QUIC and ECH + 2025-11-21 d68aec8db1 runtime: replace trace seqlock with write flag + 2025-11-21 8d9906cd34 runtime/trace: add Log benchmark + 2025-11-21 6aeacdff38 cmd/go: support sha1 repos when git default is sha256 + 2025-11-21 9570036ca5 crypto/sha3: make the zero value of SHAKE useable + 2025-11-21 155efbbeeb crypto/sha3: make the zero value of SHA3 useable + 2025-11-21 6f16669e34 database/sql: don't ignore ColumnConverter for unknown input count + 2025-11-21 121bc3e464 runtime/pprof: remove hard-coded sleep in CPU profile reader + 2025-11-21 b604148c4e runtime: fix double wakeup in CPU profile buffer + 2025-11-21 22f24f90b5 cmd/compile: change testing.B.Loop keep alive semantic + 2025-11-21 cfb9d2eb73 net: remove unused linknames + 2025-11-21 65ef314f89 net/http: remove unused linknames + 2025-11-21 0f32fbc631 net/http: populate Response.Request when using NewFileTransport + 2025-11-21 3e0a8e7867 net/http: preserve original path encoding in redirects + 2025-11-21 831af61120 net/http: use HTTP 307 redirects in ServeMux + 2025-11-21 87269224cb net/http: update Response.Request.URL after redirects on GOOS=js + 2025-11-21 7aa9ca729f net/http/cookiejar: treat localhost as secure origin + 2025-11-21 f870a1d398 net/url: warn that JoinPath arguments should be escaped + 2025-11-21 9962d95fed crypto/internal/fips140/mldsa: unroll NTT and inverseNTT + 2025-11-21 f821fc46c5 crypto/internal/fisp140test: update acvptool, test data + 2025-11-21 b59efc38a0 crypto/internal/fips140/mldsa: new package + 2025-11-21 62741480b8 runtime: remove linkname for gopanic + 2025-11-21 7db2f0bb9a crypto/internal/hpke: separate KEM and PublicKey/PrivateKey interfaces + 2025-11-21 e15800c0ec crypto/internal/hpke: add ML-KEM and hybrid KEMs, and SHAKE KDFs + 2025-11-21 7c985a2df4 crypto/internal/hpke: modularize API and support more ciphersuites + 2025-11-21 e7d47ac33d cmd/compile: simplify negative on multiplication + 2025-11-21 35d2712b32 net/http: fix typo in Transport docs + 2025-11-21 90c970cd0f net: remove unnecessary loop variable copies in tests + 2025-11-21 9772d3a690 cmd/cgo: strip top-level const qualifier from argument frame struct + 2025-11-21 1903782ade errors: add examples for custom Is/As matching + 2025-11-21 ec92bc6d63 cmd/compile: rewrite Rsh to RshU if arguments are proved positive + 2025-11-21 3820f94c1d cmd/compile: propagate unsigned relations for Rsh if arguments are positive + 2025-11-21 d474f1fd21 cmd/compile: make dse track multiple shadowed ranges + 2025-11-21 d0d0a72980 cmd/compile/internal/ssa: correct type of ARM64 conditional instructions + 2025-11-21 a9704f89ea internal/runtime/gc/scan: add AVX512 impl of filterNil. + 2025-11-21 ccd389036a cmd/internal/objabi: remove -V=goexperiment internal special case + 2025-11-21 e7787b9eca runtime: go fmt + 2025-11-21 17b3b98796 internal/strconv: go fmt + 2025-11-21 c851827c68 internal/trace: go fmt + 2025-11-21 f87aaec53d cmd/compile: fix integer overflow in prove pass + 2025-11-21 dbd2ab9992 cmd/compile/internal: fix typos + 2025-11-21 b9d86baae3 cmd/compile/internal/devirtualize: fix typos + 2025-11-20 4b0e3cc1d6 cmd/link: support loading R_LARCH_PCREL20_S2 and R_LARCH_CALL36 relocs + 2025-11-20 cdba82c7d6 cmd/internal/obj/loong64: add {,X}VSLT.{B/H/W/V}{,U} instructions support + 2025-11-20 bd2b117c2c crypto/tls: add QUICErrorEvent + 2025-11-20 3ad2e113fc net/http/httputil: wrap ReverseProxy's outbound request body so Close is a noop + 2025-11-20 d58b733646 runtime: track goroutine location until actual STW + 2025-11-20 1bc54868d4 cmd/vendor: update to x/tools@68724af + 2025-11-20 8c3195973b runtime: disable stack allocation tests on sanitizers + 2025-11-20 ff654ea100 net/url: permit colons in the host of postgresql:// URLs + 2025-11-20 a662badab9 encoding/json: remove linknames + 2025-11-20 5afe237d65 mime: add missing path for mime types in godoc + 2025-11-20 c1b7112af8 os/signal: make NotifyContext cancel the context with a cause Change-Id: Ib93ef643be610dfbdd83ff45095a7b1ca2537b8b
Diffstat (limited to 'src/cmd/internal/obj')
-rw-r--r--src/cmd/internal/obj/arm64/asm7.go27
-rw-r--r--src/cmd/internal/obj/fips140.go6
-rw-r--r--src/cmd/internal/obj/loong64/a.out.go17
-rw-r--r--src/cmd/internal/obj/loong64/anames.go16
-rw-r--r--src/cmd/internal/obj/loong64/asm.go143
-rw-r--r--src/cmd/internal/obj/riscv/asm_test.go181
6 files changed, 303 insertions, 87 deletions
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index ccf8eda495..7addf0ddad 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -1674,32 +1674,7 @@ func log2(x uint64) uint32 {
if x == 0 {
panic("log2 of 0")
}
- n := uint32(0)
- if x >= 1<<32 {
- x >>= 32
- n += 32
- }
- if x >= 1<<16 {
- x >>= 16
- n += 16
- }
- if x >= 1<<8 {
- x >>= 8
- n += 8
- }
- if x >= 1<<4 {
- x >>= 4
- n += 4
- }
- if x >= 1<<2 {
- x >>= 2
- n += 2
- }
- if x >= 1<<1 {
- x >>= 1
- n += 1
- }
- return n
+ return uint32(bits.Len64(x) - 1)
}
func autoclass(l int64) int {
diff --git a/src/cmd/internal/obj/fips140.go b/src/cmd/internal/obj/fips140.go
index da18b64178..8f5b0c4b82 100644
--- a/src/cmd/internal/obj/fips140.go
+++ b/src/cmd/internal/obj/fips140.go
@@ -354,8 +354,10 @@ func (s *LSym) checkFIPSReloc(ctxt *Link, rel Reloc) {
objabi.R_CALLLOONG64,
objabi.R_CALLPOWER,
objabi.R_GOTPCREL,
- objabi.R_LOONG64_ADDR_LO, // used with PC-relative load
- objabi.R_LOONG64_ADDR_HI, // used with PC-relative load
+ objabi.R_LOONG64_ADDR_LO, // used with PC-relative load
+ objabi.R_LOONG64_ADDR_HI, // used with PC-relative load
+ objabi.R_LOONG64_ADDR_PCREL20_S2, // used with PC-relative load
+ objabi.R_LOONG64_CALL36,
objabi.R_LOONG64_TLS_LE_HI,
objabi.R_LOONG64_TLS_LE_LO,
objabi.R_LOONG64_TLS_IE_HI,
diff --git a/src/cmd/internal/obj/loong64/a.out.go b/src/cmd/internal/obj/loong64/a.out.go
index 5b8bffc9f1..2eabe9bda8 100644
--- a/src/cmd/internal/obj/loong64/a.out.go
+++ b/src/cmd/internal/obj/loong64/a.out.go
@@ -912,6 +912,23 @@ const (
AVSEQV
AXVSEQV
+ AVSLTB
+ AVSLTH
+ AVSLTW
+ AVSLTV
+ AVSLTBU
+ AVSLTHU
+ AVSLTWU
+ AVSLTVU
+ AXVSLTB
+ AXVSLTH
+ AXVSLTW
+ AXVSLTV
+ AXVSLTBU
+ AXVSLTHU
+ AXVSLTWU
+ AXVSLTVU
+
// LSX and LASX integer div and mod instructions
AVDIVB
AVDIVH
diff --git a/src/cmd/internal/obj/loong64/anames.go b/src/cmd/internal/obj/loong64/anames.go
index 1749b43bf6..92e3cab950 100644
--- a/src/cmd/internal/obj/loong64/anames.go
+++ b/src/cmd/internal/obj/loong64/anames.go
@@ -400,6 +400,22 @@ var Anames = []string{
"XVSEQW",
"VSEQV",
"XVSEQV",
+ "VSLTB",
+ "VSLTH",
+ "VSLTW",
+ "VSLTV",
+ "VSLTBU",
+ "VSLTHU",
+ "VSLTWU",
+ "VSLTVU",
+ "XVSLTB",
+ "XVSLTH",
+ "XVSLTW",
+ "XVSLTV",
+ "XVSLTBU",
+ "XVSLTHU",
+ "XVSLTWU",
+ "XVSLTVU",
"VDIVB",
"VDIVH",
"VDIVW",
diff --git a/src/cmd/internal/obj/loong64/asm.go b/src/cmd/internal/obj/loong64/asm.go
index b35e49a1b6..857ef31ca3 100644
--- a/src/cmd/internal/obj/loong64/asm.go
+++ b/src/cmd/internal/obj/loong64/asm.go
@@ -65,26 +65,19 @@ var optab = []Optab{
{AMOVWU, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 12, 4, 0, 0},
{ASUB, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
- {ASUBV, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
{AADD, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
{AADDV, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
{AAND, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
{ASUB, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
- {ASUBV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
{AADD, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
{AADDV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
{AAND, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
{ANEGW, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
- {ANEGV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
{AMASKEQZ, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
{ASLL, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
{ASLL, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
{ASLLV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
{ASLLV, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
- {AMUL, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
- {AMUL, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
- {AMULV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
- {AMULV, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
{AADDF, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 2, 4, 0, 0},
{AADDF, C_FREG, C_FREG, C_NONE, C_FREG, C_NONE, 2, 4, 0, 0},
{ACMPEQF, C_FREG, C_FREG, C_NONE, C_FCCREG, C_NONE, 2, 4, 0, 0},
@@ -93,6 +86,14 @@ var optab = []Optab{
{AXVSEQB, C_XREG, C_XREG, C_NONE, C_XREG, C_NONE, 2, 4, 0, 0},
{AVSEQB, C_S5CON, C_VREG, C_NONE, C_VREG, C_NONE, 22, 4, 0, 0},
{AXVSEQB, C_S5CON, C_XREG, C_NONE, C_XREG, C_NONE, 22, 4, 0, 0},
+
+ {AVSLTB, C_VREG, C_VREG, C_NONE, C_VREG, C_NONE, 2, 4, 0, 0},
+ {AXVSLTB, C_XREG, C_XREG, C_NONE, C_XREG, C_NONE, 2, 4, 0, 0},
+ {AVSLTB, C_S5CON, C_VREG, C_NONE, C_VREG, C_NONE, 22, 4, 0, 0},
+ {AXVSLTB, C_S5CON, C_XREG, C_NONE, C_XREG, C_NONE, 22, 4, 0, 0},
+ {AVSLTB, C_U5CON, C_VREG, C_NONE, C_VREG, C_NONE, 31, 4, 0, 0},
+ {AXVSLTB, C_U5CON, C_XREG, C_NONE, C_XREG, C_NONE, 31, 4, 0, 0},
+
{AVANDV, C_VREG, C_VREG, C_NONE, C_VREG, C_NONE, 2, 4, 0, 0},
{AVANDV, C_VREG, C_NONE, C_NONE, C_VREG, C_NONE, 2, 4, 0, 0},
{AXVANDV, C_XREG, C_XREG, C_NONE, C_XREG, C_NONE, 2, 4, 0, 0},
@@ -1495,26 +1496,6 @@ func buildop(ctxt *obj.Link) {
opset(ALL, r0)
opset(ALLV, r0)
- case AMUL:
- opset(AMULU, r0)
- opset(AMULH, r0)
- opset(AMULHU, r0)
- opset(AREM, r0)
- opset(AREMU, r0)
- opset(ADIV, r0)
- opset(ADIVU, r0)
- opset(AMULWVW, r0)
- opset(AMULWVWU, r0)
-
- case AMULV:
- opset(AMULVU, r0)
- opset(AMULHV, r0)
- opset(AMULHVU, r0)
- opset(AREMV, r0)
- opset(AREMVU, r0)
- opset(ADIVV, r0)
- opset(ADIVVU, r0)
-
case ASLL:
opset(ASRL, r0)
opset(ASRA, r0)
@@ -1533,9 +1514,26 @@ func buildop(ctxt *obj.Link) {
case ASUB:
opset(ASUBU, r0)
opset(ANOR, r0)
-
- case ASUBV:
+ opset(ASUBV, r0)
opset(ASUBVU, r0)
+ opset(AMUL, r0)
+ opset(AMULU, r0)
+ opset(AMULH, r0)
+ opset(AMULHU, r0)
+ opset(AREM, r0)
+ opset(AREMU, r0)
+ opset(ADIV, r0)
+ opset(ADIVU, r0)
+ opset(AMULV, r0)
+ opset(AMULVU, r0)
+ opset(AMULHV, r0)
+ opset(AMULHVU, r0)
+ opset(AREMV, r0)
+ opset(AREMVU, r0)
+ opset(ADIVV, r0)
+ opset(ADIVVU, r0)
+ opset(AMULWVW, r0)
+ opset(AMULWVWU, r0)
case ASYSCALL:
opset(ADBAR, r0)
@@ -1555,6 +1553,9 @@ func buildop(ctxt *obj.Link) {
opset(AALSLW, r0)
opset(AALSLWU, r0)
+ case ANEGW:
+ opset(ANEGV, r0)
+
case AMOVW,
AMOVD,
AMOVF,
@@ -1567,8 +1568,6 @@ func buildop(ctxt *obj.Link) {
AXVMOVQ,
AVSHUFB,
AXVSHUFB,
- ANEGW,
- ANEGV,
AWORD,
APRELD,
APRELDX,
@@ -1784,6 +1783,24 @@ func buildop(ctxt *obj.Link) {
opset(AXVSHUFW, r0)
opset(AXVSHUFV, r0)
+ case AVSLTB:
+ opset(AVSLTH, r0)
+ opset(AVSLTW, r0)
+ opset(AVSLTV, r0)
+ opset(AVSLTBU, r0)
+ opset(AVSLTHU, r0)
+ opset(AVSLTWU, r0)
+ opset(AVSLTVU, r0)
+
+ case AXVSLTB:
+ opset(AXVSLTH, r0)
+ opset(AXVSLTW, r0)
+ opset(AXVSLTV, r0)
+ opset(AXVSLTBU, r0)
+ opset(AXVSLTHU, r0)
+ opset(AXVSLTWU, r0)
+ opset(AXVSLTVU, r0)
+
case AVANDB:
opset(AVORB, r0)
opset(AVXORB, r0)
@@ -3379,6 +3396,38 @@ func (c *ctxt0) oprrr(a obj.As) uint32 {
return 0x0e003 << 15 // vseq.d
case AXVSEQV:
return 0x0e803 << 15 // xvseq.d
+ case AVSLTB:
+ return 0x0E00C << 15 // vslt.b
+ case AVSLTH:
+ return 0x0E00D << 15 // vslt.h
+ case AVSLTW:
+ return 0x0E00E << 15 // vslt.w
+ case AVSLTV:
+ return 0x0E00F << 15 // vslt.d
+ case AVSLTBU:
+ return 0x0E010 << 15 // vslt.bu
+ case AVSLTHU:
+ return 0x0E011 << 15 // vslt.hu
+ case AVSLTWU:
+ return 0x0E012 << 15 // vslt.wu
+ case AVSLTVU:
+ return 0x0E013 << 15 // vslt.du
+ case AXVSLTB:
+ return 0x0E80C << 15 // xvslt.b
+ case AXVSLTH:
+ return 0x0E80D << 15 // xvslt.h
+ case AXVSLTW:
+ return 0x0E80E << 15 // xvslt.w
+ case AXVSLTV:
+ return 0x0E80F << 15 // xvslt.d
+ case AXVSLTBU:
+ return 0x0E810 << 15 // xvslt.bu
+ case AXVSLTHU:
+ return 0x0E811 << 15 // xvslt.hu
+ case AXVSLTWU:
+ return 0x0E812 << 15 // xvslt.wu
+ case AXVSLTVU:
+ return 0x0E813 << 15 // xvslt.du
case AVANDV:
return 0x0E24C << 15 // vand.v
case AVORV:
@@ -4399,6 +4448,38 @@ func (c *ctxt0) opirr(a obj.As) uint32 {
return 0x0ED02 << 15 // xvseqi.w
case AXVSEQV:
return 0x0ED03 << 15 // xvseqi.d
+ case AVSLTB:
+ return 0x0E50C << 15 // vslti.b
+ case AVSLTH:
+ return 0x0E50D << 15 // vslti.h
+ case AVSLTW:
+ return 0x0E50E << 15 // vslti.w
+ case AVSLTV:
+ return 0x0E50F << 15 // vslti.d
+ case AVSLTBU:
+ return 0x0E510 << 15 // vslti.bu
+ case AVSLTHU:
+ return 0x0E511 << 15 // vslti.hu
+ case AVSLTWU:
+ return 0x0E512 << 15 // vslti.wu
+ case AVSLTVU:
+ return 0x0E513 << 15 // vslti.du
+ case AXVSLTB:
+ return 0x0ED0C << 15 // xvslti.b
+ case AXVSLTH:
+ return 0x0ED0D << 15 // xvslti.h
+ case AXVSLTW:
+ return 0x0ED0E << 15 // xvslti.w
+ case AXVSLTV:
+ return 0x0ED0F << 15 // xvslti.d
+ case AXVSLTBU:
+ return 0x0ED10 << 15 // xvslti.bu
+ case AXVSLTHU:
+ return 0x0ED11 << 15 // xvslti.hu
+ case AXVSLTWU:
+ return 0x0ED12 << 15 // xvslti.wu
+ case AXVSLTVU:
+ return 0x0ED13 << 15 // xvslti.du
case AVROTRB:
return 0x1ca8<<18 | 0x1<<13 // vrotri.b
case AVROTRH:
diff --git a/src/cmd/internal/obj/riscv/asm_test.go b/src/cmd/internal/obj/riscv/asm_test.go
index 5b50d1533a..f143e70103 100644
--- a/src/cmd/internal/obj/riscv/asm_test.go
+++ b/src/cmd/internal/obj/riscv/asm_test.go
@@ -17,7 +17,8 @@ import (
)
// TestLargeBranch generates a large function with a very far conditional
-// branch, in order to ensure that it assembles successfully.
+// branch, in order to ensure that it assembles correctly. This requires
+// inverting the branch and using a jump to reach the target.
func TestLargeBranch(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test in short mode")
@@ -26,6 +27,23 @@ func TestLargeBranch(t *testing.T) {
dir := t.TempDir()
+ 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
+
+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 function.
buf := bytes.NewBuffer(make([]byte, 0, 7000000))
genLargeBranch(buf)
@@ -36,27 +54,62 @@ func TestLargeBranch(t *testing.T) {
}
// Assemble generated file.
- cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), "-S", tmpfile)
cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
out, err := cmd.CombinedOutput()
if err != nil {
+ t.Errorf("Failed to assemble: %v\n%s", err, out)
+ }
+
+ // The expected instruction sequence for the long branch is:
+ // BNEZ
+ // AUIPC $..., X31
+ // JALR X0, $..., X31
+ want := regexp.MustCompile(`\sBNEZ\s.*\s.*\n.*\n.*AUIPC\s\$\d+, X31.*\n.*JALR\sX0, \$\d+, ?X31`)
+ if !want.Match(out) {
+ t.Error("Missing assembly instructions")
+ }
+
+ // Build generated files.
+ cmd = testenv.Command(t, testenv.GoToolPath(t), "build", "-o", "x.exe", "-ldflags=-linkmode=internal")
+ cmd.Dir = dir
+ cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
+ out, err = cmd.CombinedOutput()
+ if err != nil {
t.Errorf("Build failed: %v, output: %s", err, out)
}
+
+ if runtime.GOARCH == "riscv64" && runtime.GOOS == "linux" {
+ cmd = testenv.Command(t, filepath.Join(dir, "x.exe"))
+ out, err = cmd.CombinedOutput()
+ if err != nil {
+ t.Errorf("Failed to run test binary: %v", err)
+ }
+ if string(out) != "1" {
+ t.Errorf(`Got test output %q, want "2"`, string(out))
+ }
+ }
}
func genLargeBranch(buf *bytes.Buffer) {
- fmt.Fprintln(buf, "TEXT f(SB),0,$0-0")
- fmt.Fprintln(buf, "BEQ X0, X0, label")
- for i := 0; i < 1<<19; i++ {
+ fmt.Fprintln(buf, "TEXT ·x(SB),0,$0-8")
+ fmt.Fprintln(buf, "MOV X0, X10")
+ fmt.Fprintln(buf, "BEQZ X10, label")
+ for i := 0; i < 1<<18; i++ {
+ // Use a non-compressable instruction.
fmt.Fprintln(buf, "ADD $0, X5, X0")
}
+ fmt.Fprintln(buf, "ADD $1, X10, X10")
fmt.Fprintln(buf, "label:")
- fmt.Fprintln(buf, "ADD $0, X5, X0")
+ fmt.Fprintln(buf, "ADD $1, X10, X10")
+ fmt.Fprintln(buf, "MOV X10, r+0(FP)")
+ fmt.Fprintln(buf, "RET")
}
// TestLargeCall generates a large function (>1MB of text) with a call to
// a following function, in order to ensure that it assembles and links
-// correctly.
+// correctly. This requires the use of AUIPC+JALR instruction sequences,
+// which are fixed up by the linker.
func TestLargeCall(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test in short mode")
@@ -69,12 +122,15 @@ func TestLargeCall(t *testing.T) {
t.Fatalf("Failed to write file: %v\n", err)
}
main := `package main
+
+import "fmt"
+
func main() {
- x()
+ fmt.Print(x())
}
-func x()
-func y()
+func x() uint64
+func y() uint64
`
if err := os.WriteFile(filepath.Join(dir, "x.go"), []byte(main), 0644); err != nil {
t.Fatalf("failed to write main: %v\n", err)
@@ -84,51 +140,94 @@ func y()
buf := bytes.NewBuffer(make([]byte, 0, 7000000))
genLargeCall(buf)
- if err := os.WriteFile(filepath.Join(dir, "x.s"), buf.Bytes(), 0644); err != nil {
+ tmpfile := filepath.Join(dir, "x.s")
+ if err := os.WriteFile(tmpfile, buf.Bytes(), 0644); err != nil {
t.Fatalf("Failed to write file: %v\n", err)
}
+ // Assemble generated file.
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), "-S", tmpfile)
+ cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Errorf("Failed to assemble: %v\n%s", err, out)
+ }
+
+ // The expected instruction sequence for the long call is:
+ // AUIPC $0, $0, X31
+ // JALR X.., X31
+ want := regexp.MustCompile(`\sAUIPC\s\$0, \$0, X31.*\n.*\sJALR\sX.*, X31`)
+ if !want.Match(out) {
+ t.Error("Missing assembly instructions")
+ }
+
// Build generated files.
- cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-ldflags=-linkmode=internal")
+ cmd = testenv.Command(t, testenv.GoToolPath(t), "build", "-o", "x.exe", "-ldflags=-linkmode=internal")
cmd.Dir = dir
cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
- out, err := cmd.CombinedOutput()
+ out, err = cmd.CombinedOutput()
if err != nil {
t.Errorf("Build failed: %v, output: %s", err, out)
}
+ if runtime.GOARCH == "riscv64" && runtime.GOOS == "linux" {
+ cmd = testenv.Command(t, filepath.Join(dir, "x.exe"))
+ out, err = cmd.CombinedOutput()
+ if err != nil {
+ t.Errorf("Failed to run test binary: %v", err)
+ }
+ if string(out) != "2" {
+ t.Errorf(`Got test output %q, want "2"`, string(out))
+ }
+ }
+
if runtime.GOARCH == "riscv64" && testenv.HasCGO() {
- cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-ldflags=-linkmode=external")
+ cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", "x.exe", "-ldflags=-linkmode=external")
cmd.Dir = dir
cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
out, err := cmd.CombinedOutput()
if err != nil {
t.Errorf("Build failed: %v, output: %s", err, out)
}
+
+ if runtime.GOARCH == "riscv64" && runtime.GOOS == "linux" {
+ cmd = testenv.Command(t, filepath.Join(dir, "x.exe"))
+ out, err = cmd.CombinedOutput()
+ if err != nil {
+ t.Errorf("Failed to run test binary: %v", err)
+ }
+ if string(out) != "2" {
+ t.Errorf(`Got test output %q, want "2"`, string(out))
+ }
+ }
}
}
func genLargeCall(buf *bytes.Buffer) {
- fmt.Fprintln(buf, "TEXT ·x(SB),0,$0-0")
+ fmt.Fprintln(buf, "TEXT ·x(SB),0,$0-8")
+ fmt.Fprintln(buf, "MOV X0, X10")
fmt.Fprintln(buf, "CALL ·y(SB)")
- for i := 0; i < 1<<19; i++ {
+ fmt.Fprintln(buf, "ADD $1, X10, X10")
+ fmt.Fprintln(buf, "MOV X10, r+0(FP)")
+ fmt.Fprintln(buf, "RET")
+ for i := 0; i < 1<<18; i++ {
+ // Use a non-compressable instruction.
fmt.Fprintln(buf, "ADD $0, X5, X0")
}
+ fmt.Fprintln(buf, "ADD $1, X10, X10")
fmt.Fprintln(buf, "RET")
fmt.Fprintln(buf, "TEXT ·y(SB),0,$0-0")
- fmt.Fprintln(buf, "ADD $0, X5, X0")
+ fmt.Fprintln(buf, "ADD $1, X10, X10")
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.
+// This requires the use of AUIPC+JALR instruction sequences.
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()
@@ -154,22 +253,46 @@ func x() uint64
buf := bytes.NewBuffer(make([]byte, 0, 7000000))
genLargeJump(buf)
- if err := os.WriteFile(filepath.Join(dir, "x.s"), buf.Bytes(), 0644); err != nil {
+ tmpfile := filepath.Join(dir, "x.s")
+ if err := os.WriteFile(tmpfile, buf.Bytes(), 0644); err != nil {
t.Fatalf("Failed to write file: %v\n", err)
}
+ // Assemble generated file.
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), "-S", tmpfile)
+ cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Errorf("Failed to assemble: %v\n%s", err, out)
+ }
+
+ // The expected instruction sequence for the long call is:
+ // AUIPC $..., X31
+ // JALR X0, $.., X31
+ want := regexp.MustCompile(`\sAUIPC\s\$\d+, X31.*\n.*\sJALR\sX0, \$\d+, ?X31`)
+ if !want.Match(out) {
+ t.Error("Missing assembly instructions")
+ t.Errorf("%s", out)
+ }
+
// Build generated files.
- cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", "x.exe")
+ cmd = testenv.Command(t, testenv.GoToolPath(t), "build", "-o", "x.exe")
cmd.Dir = dir
- out, err := cmd.CombinedOutput()
+ cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
+ 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))
+ if runtime.GOARCH == "riscv64" && runtime.GOOS == "linux" {
+ cmd = testenv.Command(t, filepath.Join(dir, "x.exe"))
+ out, err = cmd.CombinedOutput()
+ if err != nil {
+ t.Errorf("Failed to run test binary: %v", err)
+ }
+ if string(out) != "1" {
+ t.Errorf(`Got test output %q, want "1"`, string(out))
+ }
}
}
@@ -178,8 +301,10 @@ func genLargeJump(buf *bytes.Buffer) {
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")
+ // Use a non-compressable instruction.
+ fmt.Fprintln(buf, "ADD $0, X5, X0")
}
+ 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)")