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,