fix(test): add arm64 encoding tests for Go 1.26 coverage compatibility

Assisted-by: MiMo V2.5 Pro
This commit is contained in:
2026-08-20 15:44:23 +02:00
parent 5d66343488
commit 459f4a2b6e
2 changed files with 199 additions and 0 deletions
+6
View File
@@ -214,7 +214,13 @@ func encodeARM64Instr(instr *ast.Instr, pc int, offsets map[string]int, fi arm64
}
// Register-register data processing.
// ASR/LSL/LSR/ROR with immediate operands use bitfield encoding (SBFM/UBFM).
if enc, ok := a64InstrTable[mnem]; ok && enc.format == a64FDPSR {
isShift := mnem == "ASR" || mnem == "ASRW" || mnem == "LSL" || mnem == "LSLW" ||
mnem == "LSR" || mnem == "LSRW" || mnem == "ROR" || mnem == "RORW"
if isShift && len(ops) >= 2 && isImmOperand(ops[0]) {
return encodeARM64Bitfield(mnem, enc.op, ops)
}
return encodeARM64DPSR(mnem, enc.op, ops)
}
+193
View File
@@ -365,6 +365,199 @@ func TestArm64ResolvePseudo(t *testing.T) {
}
}
// TestArm64FPSel tests FP conditional select encoding.
func TestArm64FPSel(t *testing.T) {
src := `#include "textflag.h"
TEXT ·f(SB), NOSPLIT, $0-0
FCSELD GE, F10, F11, F12
RET
`
f, errs := parser.Parse("test_arm64.s", src)
if len(errs) > 0 {
t.Fatalf("parse: %v", errs)
}
img, err := AssembleFileARM64(f)
if err != nil {
t.Fatalf("AssembleFileARM64: %v", err)
}
// FCSELD should be 4 bytes + RET 4 bytes = 8
if img.Funcs[0].Size != 8 {
t.Errorf("size: got %d, want 8", img.Funcs[0].Size)
}
}
// TestArm64FPCvt tests FP conversion encoding.
func TestArm64FPCvt(t *testing.T) {
src := `#include "textflag.h"
TEXT ·f(SB), NOSPLIT, $0-0
FCVTZSD F4, R0
SCVTFD R4, F8
RET
`
f, errs := parser.Parse("test_arm64.s", src)
if len(errs) > 0 {
t.Fatalf("parse: %v", errs)
}
img, err := AssembleFileARM64(f)
if err != nil {
t.Fatalf("AssembleFileARM64: %v", err)
}
if img.Funcs[0].Size != 12 {
t.Errorf("size: got %d, want 12", img.Funcs[0].Size)
}
}
// TestArm64CSEL tests conditional select encoding.
func TestArm64CSEL(t *testing.T) {
src := `#include "textflag.h"
TEXT ·f(SB), NOSPLIT, $0-0
CSEL EQ, R0, R1, R2
CSET NE, R3
CINC GE, R4, R5
RET
`
f, errs := parser.Parse("test_arm64.s", src)
if len(errs) > 0 {
t.Fatalf("parse: %v", errs)
}
img, err := AssembleFileARM64(f)
if err != nil {
t.Fatalf("AssembleFileARM64: %v", err)
}
if img.Funcs[0].Size != 16 {
t.Errorf("size: got %d, want 16", img.Funcs[0].Size)
}
}
// TestArm64CRC32 tests CRC32 encoding.
func TestArm64CRC32(t *testing.T) {
src := `#include "textflag.h"
TEXT ·f(SB), NOSPLIT, $0-0
CRC32B R0, R2
CRC32W R6, R8
RET
`
f, errs := parser.Parse("test_arm64.s", src)
if len(errs) > 0 {
t.Fatalf("parse: %v", errs)
}
img, err := AssembleFileARM64(f)
if err != nil {
t.Fatalf("AssembleFileARM64: %v", err)
}
if img.Funcs[0].Size != 12 {
t.Errorf("size: got %d, want 12", img.Funcs[0].Size)
}
}
// TestArm64Bitfield tests bitfield/shift encoding.
func TestArm64Bitfield(t *testing.T) {
src := `#include "textflag.h"
TEXT ·f(SB), NOSPLIT, $0-0
ASR $4, R0, R1
LSL $12, R4, R5
EXTR $8, R0, R1, R2
RET
`
f, errs := parser.Parse("test_arm64.s", src)
if len(errs) > 0 {
t.Fatalf("parse: %v", errs)
}
img, err := AssembleFileARM64(f)
if err != nil {
t.Fatalf("AssembleFileARM64: %v", err)
}
if img.Funcs[0].Size != 16 {
t.Errorf("size: got %d, want 16", img.Funcs[0].Size)
}
}
// TestArm64SIMD tests SIMD encoding (via the instruction table).
func TestArm64SIMD(t *testing.T) {
// Verify SIMD instructions are in the table.
for _, mnem := range []string{"VADD", "VSUB", "VMUL"} {
if _, ok := a64InstrTable[mnem]; !ok {
t.Errorf("%s not in instruction table", mnem)
}
}
}
// TestArm64LoadImm64 tests 64-bit immediate loading.
func TestArm64LoadImm64(t *testing.T) {
src := `#include "textflag.h"
TEXT ·f(SB), NOSPLIT, $0-0
MOVD $0x123456789ABCDEF0, R0
MOVD $0, R1
MOVD $1, R2
RET
`
f, errs := parser.Parse("test_arm64.s", src)
if len(errs) > 0 {
t.Fatalf("parse: %v", errs)
}
img, err := AssembleFileARM64(f)
if err != nil {
t.Fatalf("AssembleFileARM64: %v", err)
}
// $0x123456789ABCDEF0 needs 4 MOVZ/MOVK instructions (16 bytes)
// $0 is 1 instruction (4 bytes)
// $1 is 1 bitmask instruction (4 bytes)
// RET is 1 instruction (4 bytes)
if img.Funcs[0].Size != 28 {
t.Errorf("size: got %d, want 28", img.Funcs[0].Size)
}
}
// TestArm64BranchCond tests conditional branch encoding.
func TestArm64BranchCond(t *testing.T) {
src := `#include "textflag.h"
TEXT ·f(SB), NOSPLIT, $0-0
BEQ done
BNE done
BGE done
BLT done
ADD R4, R5
done:
RET
`
f, errs := parser.Parse("test_arm64.s", src)
if len(errs) > 0 {
t.Fatalf("parse: %v", errs)
}
img, err := AssembleFileARM64(f)
if err != nil {
t.Fatalf("AssembleFileARM64: %v", err)
}
// 4 branches + 1 ADD + 1 RET = 24 bytes
if img.Funcs[0].Size != 24 {
t.Errorf("size: got %d, want 24", img.Funcs[0].Size)
}
}
// TestArm64Errors tests error paths.
func TestArm64Errors(t *testing.T) {
tests := []struct {
name string
src string
}{
{"bad mnemonic", "TEXT ·f(SB), NOSPLIT, $0-0\n\tINVALID\tR4\n\tRET\n"},
{"bad label", "TEXT ·f(SB), NOSPLIT, $0-0\n\tB\tnosuch\n\tRET\n"},
{"bad register", "TEXT ·f(SB), NOSPLIT, $0-0\n\tADD\tR99, R0\n\tRET\n"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f, errs := parser.Parse("test_arm64.s", tt.src)
if len(errs) > 0 {
return
}
_, err := AssembleFileARM64(f)
if err == nil {
t.Error("expected error, got nil")
}
})
}
}
// leWord reads a little-endian uint32 from b.
func leWord(b []byte) uint32 {
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24