feat(asm): encode the arm64 local-exec TLS load
Assisted-by: GLM 5.3 Flash
This commit is contained in:
1 parent
5f6be4584d
commit
c27ba30862
6 files changed
+114
-2
No files matched your search
+40
-2
@@ -30,8 +30,9 @@ import (
|
||||
// (the morestack check in the prologue and the call back into the runtime in
|
||||
// the epilogue) is not emitted, so the bytes match only for NOSPLIT functions
|
||||
// or zero-frame leaves, where the toolchain emits no guard either.
|
||||
func assembleARM64(t *ast.Text) ([]byte, map[string]int, []Reloc, []LineEntry, []SpadjStep, []Arm64Literal, error) {
|
||||
func assembleARM64(t *ast.Text, tls map[string]bool) ([]byte, map[string]int, []Reloc, []LineEntry, []SpadjStep, []Arm64Literal, error) {
|
||||
fi := arm64ComputeFrame(t)
|
||||
fi.tls = tls
|
||||
prologue := arm64Prologue(fi)
|
||||
guardLen := arm64GuardLen(fi)
|
||||
chain := arm64JumpChain(t)
|
||||
@@ -1989,6 +1990,24 @@ func encodeARM64Mov(instr *ast.Instr, mnem string, wb string, fi arm64FrameInfo,
|
||||
if rd < 0 {
|
||||
return nil, fmt.Errorf("%s sym(SB): invalid destination register", mnem)
|
||||
}
|
||||
// A TLSBSS symbol's load rides the local-exec model: one MOVZ word
|
||||
// with the R_ARM64_TLS_LE relocation (asm7.go case 69), the width
|
||||
// rows existing for MOVD alone.
|
||||
if fi.tls[src.Addr.Sym.Name] {
|
||||
if mnem != "MOVD" && mnem != "MOV" {
|
||||
return nil, fmt.Errorf("%s: illegal combination: the TLS load exists for MOVD only", mnem)
|
||||
}
|
||||
if relocs != nil {
|
||||
*relocs = append(*relocs, Reloc{
|
||||
Off: 0,
|
||||
After: 4,
|
||||
Name: src.Addr.Sym.Name,
|
||||
Addend: src.Addr.Sym.Offset,
|
||||
Kind: RelArm64TLSLE,
|
||||
})
|
||||
}
|
||||
return a64wordLE(a64MoveWide(1, 2, 0, 0, uint32(rd))), nil
|
||||
}
|
||||
return encodeARM64SBLoad(src.Addr.Sym, rd, mnem, relocs)
|
||||
}
|
||||
if dst.Addr.Sym != nil && dst.Addr.Sym.Pseudo == "SB" && isMemOperand(dst) {
|
||||
@@ -2116,6 +2135,9 @@ func arm64MovSize(mnem string, ops []*ast.Operand, fi arm64FrameInfo) int {
|
||||
if mnem == "FMOVQ" {
|
||||
return 12 // ADRP + ADD + LDR: the unaligned-access fallback
|
||||
}
|
||||
if fi.tls != nil && fi.tls[src.Addr.Sym.Name] {
|
||||
return 4 // the TLS-LE load is one MOVZ word
|
||||
}
|
||||
return 8 // ADRP + LDR
|
||||
case dst.Addr.Sym != nil && dst.Addr.Sym.Pseudo == "SB":
|
||||
if mnem == "FMOVQ" {
|
||||
@@ -5771,6 +5793,22 @@ func AssembleFileARM64(f *ast.File) (*Image, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The TLS symbols: a GLOBL marked TLSBSS makes the toolchain's aclass
|
||||
// key its load off objabi.STLSBSS (asm7.go C_TLSIE), so the loads of
|
||||
// these names encode as the local-exec MOVZ with the TLS_LE relocation.
|
||||
tlsSyms := map[string]bool{}
|
||||
for _, d := range f.Decls {
|
||||
g, ok := d.(*ast.Globl)
|
||||
if !ok || g.Name == nil {
|
||||
continue
|
||||
}
|
||||
for _, fl := range g.Flags {
|
||||
if fl == "TLSBSS" {
|
||||
tlsSyms[g.Name.Name] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
img := &Image{Symbols: map[string]int{}, SourcePath: f.Path}
|
||||
var pendingLits []Arm64Literal
|
||||
litSeen := map[string]bool{}
|
||||
@@ -5779,7 +5817,7 @@ func AssembleFileARM64(f *ast.File) (*Image, error) {
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
code, labels, relocs, lines, spadj, lits, err := assembleARM64(t)
|
||||
code, labels, relocs, lines, spadj, lits, err := assembleARM64(t, tlsSyms)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", t.Name.Name, err)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user