feat(lint): abi0 register-args rule and go-asm width model
This commit is contained in:
@@ -335,3 +335,79 @@ TEXT ·f(SB), NOSPLIT, $0
|
||||
t.Fatalf("correct width must not be flagged: %+v", diags)
|
||||
}
|
||||
}
|
||||
|
||||
func TestABI0RegisterArgs(t *testing.T) {
|
||||
// A kernel with a // func signature whose parameters are never read from
|
||||
// the FP frame: the classic register-args port bug.
|
||||
diags := lintSrc(t, `
|
||||
// func kernel(text *byte, n int)
|
||||
TEXT ·kernel(SB), NOSPLIT, $0-16
|
||||
MOVQ DI, R10
|
||||
MOVQ R9, AX
|
||||
RET
|
||||
`)
|
||||
if codes(diags)[CodeABI0RegisterArgs] != 1 {
|
||||
t.Fatalf("want one abi0-register-args, got %+v", diags)
|
||||
}
|
||||
|
||||
// Reading every parameter from the frame is correct.
|
||||
diags = lintSrc(t, `
|
||||
// func kernel(text *byte, n int)
|
||||
TEXT ·kernel(SB), NOSPLIT, $0-16
|
||||
MOVQ text+0(FP), AX
|
||||
MOVQ n+8(FP), BX
|
||||
RET
|
||||
`)
|
||||
if codes(diags)[CodeABI0RegisterArgs] != 0 {
|
||||
t.Fatalf("frame-reading kernel must not be flagged: %+v", diags)
|
||||
}
|
||||
|
||||
// Only a result write to FP, no parameter read: still flagged.
|
||||
diags = lintSrc(t, `
|
||||
// func top(sa []int32) int
|
||||
TEXT ·top(SB), NOSPLIT, $0-24
|
||||
MOVQ SI, R10
|
||||
MOVQ R10, ret+16(FP)
|
||||
RET
|
||||
`)
|
||||
if codes(diags)[CodeABI0RegisterArgs] != 1 {
|
||||
t.Fatalf("result-only FP write must still be flagged: %+v", diags)
|
||||
}
|
||||
|
||||
// No signature: stay silent.
|
||||
diags = lintSrc(t, `
|
||||
TEXT ·bare(SB), NOSPLIT, $0-16
|
||||
MOVQ DI, AX
|
||||
RET
|
||||
`)
|
||||
if codes(diags)[CodeABI0RegisterArgs] != 0 {
|
||||
t.Fatalf("signature-less function must not be flagged: %+v", diags)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterWidthCanonicalNames(t *testing.T) {
|
||||
// Canonical Go asm names with an L operation: the correct spelling for a
|
||||
// 32-bit operation, never a width mismatch.
|
||||
diags := lintSrc(t, `
|
||||
#include "textflag.h"
|
||||
TEXT ·f(SB), NOSPLIT, $0
|
||||
MOVL (BX)(R9*4), SI
|
||||
XORL R9, R9
|
||||
MOVL 128(BX)(R9*4), R12
|
||||
RET
|
||||
`)
|
||||
if codes(diags)[CodeRegisterWidthMismatch] != 0 {
|
||||
t.Fatalf("canonical 64-bit names with L ops must not be flagged: %+v", diags)
|
||||
}
|
||||
|
||||
// A byte register in an L operation stays a mismatch.
|
||||
diags = lintSrc(t, `
|
||||
#include "textflag.h"
|
||||
TEXT ·f(SB), NOSPLIT, $0
|
||||
MOVL AL, DX
|
||||
RET
|
||||
`)
|
||||
if codes(diags)[CodeRegisterWidthMismatch] != 1 {
|
||||
t.Fatalf("byte register in L op must be flagged: %+v", diags)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user