feat(asm): give riscv64 the END and GETCALLERPC the toolchain accepts
Assisted-by: GLM 5.3 Flash
This commit is contained in:
1 parent
0211d6672d
commit
76f8ba6403
3 files changed
+195
-6
No files matched your search
@@ -241,6 +241,91 @@ func TestRISCVToolchainRejections(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestRISCVGetCallerPC_Differential proves the toolchain's GETCALLERPC
|
||||
// rewrite: a leaf reads the caller's address straight from the link register
|
||||
// (MOV X1, rd, compressed to C.MV; X0 stays the discarded ADDI), a body that
|
||||
// calls out reads the prologue's save at 0(SP) (LD rd, 0(SP), compressed to
|
||||
// C.LDSP, the reserved SP destination included; X0 stays uncompressed), and a
|
||||
// memory destination stores it there, through the frame mapping and the
|
||||
// static-data path alike.
|
||||
func TestRISCVGetCallerPC_Differential(t *testing.T) {
|
||||
leaf := `#include "textflag.h"
|
||||
|
||||
TEXT ·leafgcp(SB), NOSPLIT, $0
|
||||
GETCALLERPC X5 // c.mv X5, X1
|
||||
GETCALLERPC X0 // addi X0, X1, 0, discarded
|
||||
GETCALLERPC 8(X6) // sd X1, 8(X6)
|
||||
GETCALLERPC x+8(FP) // c.sdsp X1, 16
|
||||
END
|
||||
RET
|
||||
`
|
||||
path := writeRISCVSrc(t, "gcp_leaf_riscv64.s", leaf)
|
||||
assertRISCVDifferential(t, path, leaf, "leafgcp")
|
||||
|
||||
framed := `#include "textflag.h"
|
||||
|
||||
TEXT ·framegcp(SB), $8
|
||||
CALL extcall(SB)
|
||||
GETCALLERPC X5 // c.ldsp X5, 0(SP)
|
||||
GETCALLERPC X2 // c.ldsp X2, 0(SP)
|
||||
GETCALLERPC X0 // ld X0, 0(SP), uncompressed
|
||||
END
|
||||
RET
|
||||
`
|
||||
path = writeRISCVSrc(t, "gcp_frame_riscv64.s", framed)
|
||||
assertRISCVDifferential(t, path, framed, "framegcp")
|
||||
}
|
||||
|
||||
// TestRISCVGetCallerPCRejections pins the rewrite's rejections: a framed
|
||||
// body with a memory destination would read (SP) into a MOV with two memory
|
||||
// ends, a non-integer register is the rd bank rejection, and no destination
|
||||
// at all is the toolchain's unsupported MOV.
|
||||
func TestRISCVGetCallerPCRejections(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
src string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "memory destination in a framed body",
|
||||
src: "CALL extcall(SB)\n\tGETCALLERPC 8(X6)\n",
|
||||
want: "GETCALLERPC: unsupported MOV",
|
||||
},
|
||||
{
|
||||
name: "float destination",
|
||||
src: "\tGETCALLERPC F5\n",
|
||||
want: "GETCALLERPC: expected integer register in rd position but got non-integer register F5",
|
||||
},
|
||||
{
|
||||
name: "vector destination",
|
||||
src: "\tGETCALLERPC V1\n",
|
||||
want: "GETCALLERPC: expected integer register in rd position but got non-integer register V1",
|
||||
},
|
||||
{
|
||||
name: "immediate destination",
|
||||
src: "\tGETCALLERPC $5\n",
|
||||
want: "GETCALLERPC: expected integer register in rd position",
|
||||
},
|
||||
{
|
||||
name: "no destination",
|
||||
src: "\tGETCALLERPC\n",
|
||||
want: "GETCALLERPC: unsupported MOV",
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
fn := firstTextRISCV(t, "#include \"textflag.h\"\n\nTEXT ·r(SB), NOSPLIT, $0\n"+tc.src+"\tRET\n")
|
||||
_, _, _, _, _, _, err := assembleRISCV(fn, nil)
|
||||
if err == nil {
|
||||
t.Fatalf("source assembled, want rejection %q", tc.want)
|
||||
}
|
||||
if !strings.Contains(err.Error(), tc.want) {
|
||||
t.Errorf("error %q does not carry %q", err.Error(), tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestRISCVTLSRelocKind pins the relocation the TLS sequence records: one
|
||||
// R_RISCV_TLS_LE field spanning the LUI + ADDIW pair, the symbol named and
|
||||
// no addend for a plain tls(SB) reference.
|
||||
|
||||
Reference in new issue
Block a user