From 2cb2458e8f36056be9d391e9acbbe2f35625edbb Mon Sep 17 00:00:00 2001 From: Nathan Whitaker Date: Tue, 13 Dec 2022 17:29:04 -0800 Subject: [PATCH 1/5] Implement TLS on Aarch64 Mach-O --- cranelift/codegen/src/binemit/mod.rs | 10 ++++ cranelift/codegen/src/isa/aarch64/inst.isle | 12 ++++ .../codegen/src/isa/aarch64/inst/emit.rs | 58 +++++++++++++++++++ cranelift/codegen/src/isa/aarch64/inst/mod.rs | 22 +++++++ cranelift/codegen/src/isa/aarch64/lower.isle | 6 +- cranelift/object/src/backend.rs | 30 ++++++++++ 6 files changed, 137 insertions(+), 1 deletion(-) diff --git a/cranelift/codegen/src/binemit/mod.rs b/cranelift/codegen/src/binemit/mod.rs index 33bc8f641472..864e9ccb6c33 100644 --- a/cranelift/codegen/src/binemit/mod.rs +++ b/cranelift/codegen/src/binemit/mod.rs @@ -56,6 +56,14 @@ pub enum Reloc { /// Mach-O x86_64 32 bit signed PC relative offset to a `__thread_vars` entry. MachOX86_64Tlv, + /// Mach-O AAarch64 TLS + /// PC-relative distance to the page of the TLVP slot. + MachOAarch64TlsAdrPage21, + + /// Mach-O AAarch64 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) @@ -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 f7239a2adf8a..8146a619e5a9 100644 --- a/cranelift/codegen/src/isa/aarch64/inst.isle +++ b/cranelift/codegen/src/isa/aarch64/inst.isle @@ -927,6 +927,11 @@ (symbol ExternalName) (rd WritableReg)) + (MachOTlsGetAddr + (symbol ExternalName) + (rd WritableReg) + (rtmp WritableReg)) + ;; An unwind pseudo-instruction. (Unwind (inst UnwindInst)) @@ -3591,6 +3596,13 @@ (_ 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)) + (tmp WritableReg (temp_writable_reg $I64)) + (_ Unit (emit (MInst.MachOTlsGetAddr name dst tmp)))) + 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 04b9ba705fe1..4e4807ba6a3b 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs @@ -3458,6 +3458,64 @@ impl MachInstEmit for Inst { sink.put4(0xd503201f); } + &Inst::MachOTlsGetAddr { + ref symbol, + rd, + rtmp, + } => { + // 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,