fix(asm): treat the arm64 $-8 frame as frameless and encode the RET forms
Assisted-by: GLM 5.3 Flash
This commit is contained in:
1 parent
d853432dba
commit
f20aa156d0
2 files changed
+43
-2
No files matched your search
@@ -396,7 +396,7 @@ func encodeARM64Instr(instr *ast.Instr, pc int, offsets map[string]int, fi arm64
|
|||||||
// Pseudo-instructions and special cases first.
|
// Pseudo-instructions and special cases first.
|
||||||
switch mnem {
|
switch mnem {
|
||||||
case "RET":
|
case "RET":
|
||||||
return arm64Return(fi), nil
|
return arm64RetInstr(fi, ops, relocs), nil
|
||||||
case "NOP", "NOOP":
|
case "NOP", "NOOP":
|
||||||
return a64wordLE(a64NOP), nil
|
return a64wordLE(a64NOP), nil
|
||||||
case "UNDEF":
|
case "UNDEF":
|
||||||
|
|||||||
+42
-1
@@ -87,7 +87,10 @@ func arm64ComputeFrame(t *ast.Text) arm64FrameInfo {
|
|||||||
if fi.frame != 0 || !fi.leaf {
|
if fi.frame != 0 || !fi.leaf {
|
||||||
fi.autosize = fi.frame + 8 // space for the saved LR
|
fi.autosize = fi.frame + 8 // space for the saved LR
|
||||||
// The toolchain always adds an extrasize: 8 when the total leaves a
|
// The toolchain always adds an extrasize: 8 when the total leaves a
|
||||||
// 16-byte alignment gap, another 16 when already aligned.
|
// 16-byte alignment gap, another 16 when already aligned. An
|
||||||
|
// autosize of zero (the $-8 convention included) is frameless and
|
||||||
|
// takes neither.
|
||||||
|
if fi.autosize != 0 {
|
||||||
switch fi.autosize % 16 {
|
switch fi.autosize % 16 {
|
||||||
case 8:
|
case 8:
|
||||||
fi.autosize += 8
|
fi.autosize += 8
|
||||||
@@ -99,6 +102,13 @@ func arm64ComputeFrame(t *ast.Text) arm64FrameInfo {
|
|||||||
fi.autosize += 16 - (fi.autosize % 16)
|
fi.autosize += 16 - (fi.autosize % 16)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if fi.autosize == 0 {
|
||||||
|
// The NOFRAME shape: the toolchain forces the leaf mark on any
|
||||||
|
// autosize-zero function (calls included), so nothing saves LR and
|
||||||
|
// no stack-split guard runs.
|
||||||
|
fi.leaf = true
|
||||||
|
}
|
||||||
switch {
|
switch {
|
||||||
case fi.noSplit:
|
case fi.noSplit:
|
||||||
case fi.autosize < stackSmall && fi.leaf:
|
case fi.autosize < stackSmall && fi.leaf:
|
||||||
@@ -301,6 +311,37 @@ func arm64Return(fi arm64FrameInfo) []byte {
|
|||||||
return a64WordsLE(ws...)
|
return a64WordsLE(ws...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// arm64RetInstr encodes a RET. The plain form runs the frame epilogue and
|
||||||
|
// branches to LR; RET Rn runs the epilogue and branches to the register
|
||||||
|
// (asm7.go case 78); RET sym(SB) runs the epilogue and branches to the
|
||||||
|
// symbol with the call relocation, the toolchain's retJMP tail call.
|
||||||
|
func arm64RetInstr(fi arm64FrameInfo, ops []*ast.Operand, relocs *[]Reloc) []byte {
|
||||||
|
out := arm64Return(fi)
|
||||||
|
if len(ops) != 1 {
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
op := ops[0]
|
||||||
|
switch {
|
||||||
|
case op.Addr.Sym != nil && op.Addr.Sym.Pseudo == "" && op.Addr.Base == "" && op.Addr.Index == "":
|
||||||
|
if rn := arm64RegNum(op.Addr.Sym.Name); rn >= 0 {
|
||||||
|
// The operand form replaces the default BR LR word.
|
||||||
|
return append(out[:len(out)-4], a64wordLE(0xd65f0000|uint32(rn)<<5)...)
|
||||||
|
}
|
||||||
|
case op.Addr.Sym != nil && op.Addr.Sym.Pseudo == "SB" && op.Addr.Base == "" && op.Addr.Index == "":
|
||||||
|
if relocs != nil {
|
||||||
|
*relocs = append(*relocs, Reloc{
|
||||||
|
Off: 0,
|
||||||
|
After: 4,
|
||||||
|
Name: op.Addr.Sym.Name,
|
||||||
|
Addend: op.Addr.Sym.Offset,
|
||||||
|
Kind: RelArm64Branch,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return append(out[:len(out)-4], a64wordLE(0x14000000)...) // B sym(SB)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// arm64PrologueSpadjPC returns the function-relative byte offset where the
|
// arm64PrologueSpadjPC returns the function-relative byte offset where the
|
||||||
// prologue has finished decrementing SP (the delta becomes autosize).
|
// prologue has finished decrementing SP (the delta becomes autosize).
|
||||||
func arm64PrologueSpadjPC(fi arm64FrameInfo) int {
|
func arm64PrologueSpadjPC(fi arm64FrameInfo) int {
|
||||||
|
|||||||
Reference in new issue
Block a user