fix(arm64): encode shifts, divides and multiplies and align sizes with emission
Assisted-by: GLM 5.3
This commit is contained in:
@@ -152,6 +152,45 @@ func TestStackGuardBytesARM64(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestStackGuardBranchTargetsARM64 checks the class-2 guard's branch
|
||||
// positions for a frame whose guard constant needs two MOV words: the
|
||||
// displacements must be computed from byte offsets (8+4*ml and 16+4*ml), so
|
||||
// both branches land on the morestack block rather than inside the body.
|
||||
// The frame size makes the toolchain switch its own prologue decomposition,
|
||||
// so the assertion is on the branch targets, not pinned bytes.
|
||||
func TestStackGuardBranchTargetsARM64(t *testing.T) {
|
||||
f, errs := parser.Parse("g_arm64.s", "TEXT \u00b7f(SB), $65664-0\n\tCALL \u00b7other(SB)\n\tRET\nTEXT \u00b7other(SB), NOSPLIT, $0\n\tRET\n")
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("parse: %v", errs)
|
||||
}
|
||||
img, err := AssembleFileARM64(f)
|
||||
if err != nil {
|
||||
t.Fatalf("assemble: %v", err)
|
||||
}
|
||||
fn := img.Funcs[0]
|
||||
code := img.Code[fn.Offset : fn.Offset+fn.Size]
|
||||
if len(code)%4 != 0 {
|
||||
t.Fatalf("function size %d is not a word multiple", len(code))
|
||||
}
|
||||
// autosize = 65680, so the guard materialises 65552 = MOVZ+MOVK: ml = 2
|
||||
// and the branches sit at bytes 16 and 24 of the guard prefix.
|
||||
const morestackBlock = 12 // MOVD R30, R3; BL; B back
|
||||
blockStart := len(code) - morestackBlock
|
||||
check := func(name string, off int) {
|
||||
t.Helper()
|
||||
w := leWord(code[off:])
|
||||
imm19 := int32(w>>5) & 0x7FFFF
|
||||
if imm19&(1<<18) != 0 {
|
||||
imm19 -= 1 << 19
|
||||
}
|
||||
if target := off + int(imm19)*4; target != blockStart {
|
||||
t.Errorf("%s at byte %d targets byte %d, want the morestack block at %d", name, off, target, blockStart)
|
||||
}
|
||||
}
|
||||
check("B.LO", 16)
|
||||
check("B.LS", 24)
|
||||
}
|
||||
|
||||
// The riscv64 stack-split guard, pinned from `go tool asm` (Go 1.27,
|
||||
// riscv64): the morestack call sits between the guard and the body, and the
|
||||
// guard branches forward over it. Relocation fields are masked.
|
||||
|
||||
Reference in New Issue
Block a user