From 937ae9e0b43d0c213e29077040c24ea26c82b499 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Mon, 9 Oct 2023 17:11:09 +0100 Subject: [PATCH 1/2] aarch64: Implement TLSDESC for TLS GD accesses --- cranelift/codegen/src/binemit/mod.rs | 28 +++--- cranelift/codegen/src/isa/aarch64/inst.isle | 6 +- .../codegen/src/isa/aarch64/inst/emit.rs | 87 +++++++++++++++---- cranelift/codegen/src/isa/aarch64/inst/mod.rs | 21 +++-- .../filetests/isa/aarch64/tls-elf-gd.clif | 42 +++------ cranelift/object/src/backend.rs | 37 ++++++-- 6 files changed, 148 insertions(+), 73 deletions(-) diff --git a/cranelift/codegen/src/binemit/mod.rs b/cranelift/codegen/src/binemit/mod.rs index d8d804bbdc28..9eed2905c4cd 100644 --- a/cranelift/codegen/src/binemit/mod.rs +++ b/cranelift/codegen/src/binemit/mod.rs @@ -64,15 +64,21 @@ pub enum Reloc { /// 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 TLSDESC Adr Page21 + /// This is equivalent to `R_AARCH64_TLSDESC_ADR_PAGE21` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#57105thread-local-storage-descriptors) + Aarch64TlsDescAdrPage21, - /// 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, + /// Aarch64 TLSDESC Ld64 Lo12 + /// This is equivalent to `R_AARCH64_TLSDESC_LD64_LO12` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#57105thread-local-storage-descriptors) + Aarch64TlsDescLd64Lo12, + + /// Aarch64 TLSDESC Add Lo12 + /// This is equivalent to `R_AARCH64_TLSGD_ADD_LO12` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#57105thread-local-storage-descriptors) + Aarch64TlsDescAddLo12, + + /// Aarch64 TLSDESC Call + /// This is equivalent to `R_AARCH64_TLSDESC_CALL` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#57105thread-local-storage-descriptors) + Aarch64TlsDescCall, /// AArch64 GOT Page /// Set the immediate value of an ADRP to bits 32:12 of X; check that –232 <= X < 232 @@ -141,8 +147,10 @@ impl fmt::Display for Reloc { 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::Aarch64TlsDescAdrPage21 => write!(f, "Aarch64TlsDescAdrPage21"), + Self::Aarch64TlsDescLd64Lo12 => write!(f, "Aarch64TlsDescLd64Lo12"), + Self::Aarch64TlsDescAddLo12 => write!(f, "Aarch64TlsDescAddLo12"), + Self::Aarch64TlsDescCall => write!(f, "Aarch64TlsDescCall"), Self::Aarch64AdrGotPage21 => write!(f, "Aarch64AdrGotPage21"), Self::Aarch64Ld64GotLo12Nc => write!(f, "Aarch64AdrGotLo12Nc"), Self::S390xTlsGd64 => write!(f, "TlsGd64"), diff --git a/cranelift/codegen/src/isa/aarch64/inst.isle b/cranelift/codegen/src/isa/aarch64/inst.isle index 0e1d03334ffa..345afee3d7b1 100644 --- a/cranelift/codegen/src/isa/aarch64/inst.isle +++ b/cranelift/codegen/src/isa/aarch64/inst.isle @@ -948,7 +948,8 @@ ;; A call to the `ElfTlsGetAddr` libcall. Returns address of TLS symbol in x0. (ElfTlsGetAddr (symbol ExternalName) - (rd WritableReg)) + (rd WritableReg) + (tmp WritableReg)) (MachOTlsGetAddr (symbol ExternalName) @@ -3761,7 +3762,8 @@ (decl elf_tls_get_addr (ExternalName) Reg) (rule (elf_tls_get_addr name) (let ((dst WritableReg (temp_writable_reg $I64)) - (_ Unit (emit (MInst.ElfTlsGetAddr name dst)))) + (tmp WritableReg (temp_writable_reg $I64)) + (_ Unit (emit (MInst.ElfTlsGetAddr name dst tmp)))) dst)) (decl macho_tls_get_addr (ExternalName) Reg) diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit.rs b/cranelift/codegen/src/isa/aarch64/inst/emit.rs index 2742134d1f0f..e96cf2ee7921 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs @@ -4,7 +4,7 @@ use cranelift_control::ControlPlane; use regalloc2::Allocation; use crate::binemit::{Reloc, StackMap}; -use crate::ir::{self, types::*, LibCall, MemFlags, RelSourceLoc, TrapCode}; +use crate::ir::{self, types::*, MemFlags, RelSourceLoc, TrapCode}; use crate::isa::aarch64::inst::*; use crate::machinst::{ty_bits, Reg, RegClass, Writable}; use crate::trace; @@ -3537,32 +3537,81 @@ impl MachInstEmit for Inst { } } - &Inst::ElfTlsGetAddr { ref symbol, rd } => { + &Inst::ElfTlsGetAddr { + ref symbol, + rd, + tmp, + } => { let rd = allocs.next_writable(rd); + let tmp = allocs.next_writable(tmp); assert_eq!(xreg(0), rd.to_reg()); + // See the original proposal for TLSDESC. + // http://www.fsfla.org/~lxoliva/writeups/TLS/paper-lk2006.pdf + // + // Implement the TLSDESC instruction sequence: + // adrp x0, :tlsdesc:tlsvar + // ldr tmp, [x0, :tlsdesc_lo12:tlsvar] + // add x0, x0, :tlsdesc_lo12:tlsvar + // blr tmp + // mrs tmp, tpidr_el0 + // add x0, x0, tmp + // // This is the instruction sequence that GCC emits for ELF GD TLS Relocations in aarch64 - // See: https://gcc.godbolt.org/z/KhMh5Gvra + // See: https://gcc.godbolt.org/z/e4j7MdErh - // adrp x0,