feat(asm): encode the arm64 local-exec TLS load

Assisted-by: GLM 5.3 Flash
This commit is contained in:
petrbalvin committed 2026-10-07 21:34:30 +02:00
1 parent 5f6be4584d
commit c27ba30862
6 files changed
+114 -2

No files matched your search

+40 -2
View File
@@ -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)
}