From c3decdf910380624b74f834e2f04204aa950cdaa Mon Sep 17 00:00:00 2001 From: Nathan Whitaker <17734409+nathanwhit@users.noreply.github.com> Date: Fri, 24 Mar 2023 10:54:01 -0700 Subject: [PATCH] cranelift: Implement TLS on aarch64 Mach-O (Apple Silicon) (#5434) * Implement TLS on Aarch64 Mach-O * Add aarch64 macho TLS filetest * Address review comments - `Aarch64` instead of `AArch64` in comments - Remove unnecessary guard in tls_value lowering - Remove unnecessary regalloc metadata in emission * Use x1 as temporary register in emission - Instead of passing in a temporary register to use when emitting the TLS code, just use `x1`, as it's already in the clobber set. This also keeps the size of `aarch64::inst::Inst` at 32 bytes. - Update filetest accordingly * Update aarch64 mach-o TLS filetest --- cranelift/codegen/src/binemit/mod.rs | 14 ++++- cranelift/codegen/src/isa/aarch64/inst.isle | 10 ++++ .../codegen/src/isa/aarch64/inst/emit.rs | 48 +++++++++++++++ cranelift/codegen/src/isa/aarch64/inst/mod.rs | 11 ++++ cranelift/codegen/src/isa/aarch64/lower.isle | 6 +- .../filetests/isa/aarch64/tls-macho.clif | 58 +++++++++++++++++++ cranelift/object/src/backend.rs | 30 ++++++++++ 7 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 cranelift/filetests/filetests/isa/aarch64/tls-macho.clif diff --git a/cranelift/codegen/src/binemit/mod.rs b/cranelift/codegen/src/binemit/mod.rs index 33bc8f6414..2b1f57e0fe 100644 --- a/cranelift/codegen/src/binemit/mod.rs +++ b/cranelift/codegen/src/binemit/mod.rs @@ -56,12 +56,20 @@ pub enum Reloc { /// Mach-O x86_64 32 bit signed PC relative offset to a `__thread_vars` entry. MachOX86_64Tlv, - /// AArch64 TLS GD + /// Mach-O Aarch64 TLS + /// PC-relative distance to the page of the TLVP slot. + MachOAarch64TlsAdrPage21, + + /// Mach-O Aarch64 TLS + /// Offset within page of TLVP slot. + MachOAarch64TlsAdrPageOff12, + + /// Aarch64 TLS GD /// Set an ADRP immediate field to the top 21 bits of the final address. Checks for overflow. /// This is equivalent to `R_AARCH64_TLSGD_ADR_PAGE21` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#relocations-for-thread-local-storage) Aarch64TlsGdAdrPage21, - /// AArch64 TLS GD + /// Aarch64 TLS GD /// Set the add immediate field to the low 12 bits of the final address. Does not check for overflow. /// This is equivalent to `R_AARCH64_TLSGD_ADD_LO12_NC` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#relocations-for-thread-local-storage) Aarch64TlsGdAddLo12Nc, @@ -109,6 +117,8 @@ impl fmt::Display for Reloc { Self::ElfX86_64TlsGd => write!(f, "ElfX86_64TlsGd"), Self::MachOX86_64Tlv => write!(f, "MachOX86_64Tlv"), + Self::MachOAarch64TlsAdrPage21 => write!(f, "MachOAarch64TlsAdrPage21"), + Self::MachOAarch64TlsAdrPageOff12 => write!(f, "MachOAarch64TlsAdrPageOff12"), Self::Aarch64TlsGdAdrPage21 => write!(f, "Aarch64TlsGdAdrPage21"), Self::Aarch64TlsGdAddLo12Nc => write!(f, "Aarch64TlsGdAddLo12Nc"), Self::Aarch64AdrGotPage21 => write!(f, "Aarch64AdrGotPage21"), diff --git a/cranelift/codegen/src/isa/aarch64/inst.isle b/cranelift/codegen/src/isa/aarch64/inst.isle index f7239a2adf..389fac99b1 100644 --- a/cranelift/codegen/src/isa/aarch64/inst.isle +++ b/cranelift/codegen/src/isa/aarch64/inst.isle @@ -927,6 +927,10 @@ (symbol ExternalName) (rd WritableReg)) + (MachOTlsGetAddr + (symbol ExternalName) + (rd WritableReg)) + ;; An unwind pseudo-instruction. (Unwind (inst UnwindInst)) @@ -3591,6 +3595,12 @@ (_ Unit (emit (MInst.ElfTlsGetAddr name dst)))) dst)) +(decl macho_tls_get_addr (ExternalName) Reg) +(rule (macho_tls_get_addr name) + (let ((dst WritableReg (temp_writable_reg $I64)) + (_ Unit (emit (MInst.MachOTlsGetAddr name dst)))) + dst)) + ;; A tuple of `ProducesFlags` and `IntCC`. (type FlagsAndCC (enum (FlagsAndCC (flags ProducesFlags) (cc IntCC)))) diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit.rs b/cranelift/codegen/src/isa/aarch64/inst/emit.rs index 04b9ba705f..2e576fc895 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs @@ -3458,6 +3458,54 @@ impl MachInstEmit for Inst { sink.put4(0xd503201f); } + &Inst::MachOTlsGetAddr { ref symbol, rd } => { + // Each thread local variable gets a descriptor, where the first xword of the descriptor is a pointer + // to a function that takes the descriptor address in x0, and after the function returns x0 + // contains the address for the thread local variable + // + // what we want to emit is basically: + // + // adrp x0,