diff --git a/cranelift/codegen/src/isa/aarch64/inst.isle b/cranelift/codegen/src/isa/aarch64/inst.isle index d525452b4dc7..a49f8872d12c 100644 --- a/cranelift/codegen/src/isa/aarch64/inst.isle +++ b/cranelift/codegen/src/isa/aarch64/inst.isle @@ -825,7 +825,8 @@ ;; A call to the `ElfTlsGetAddr` libcall. Returns address of TLS symbol in x0. (ElfTlsGetAddr - (symbol ExternalName)) + (symbol ExternalName) + (rd WritableReg)) ;; An unwind pseudo-instruction. (Unwind @@ -3068,3 +3069,12 @@ (if (ty_vec64 ty)) (let ((src Reg (mov_from_vec src 0 (ScalarSize.Size64)))) (cmp_imm (OperandSize.Size64) src (u8_into_imm12 0)))) + +;;;; TLS Values ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Helper for emitting ElfTlsGetAddr. +(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)))) + dst)) diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit.rs b/cranelift/codegen/src/isa/aarch64/inst/emit.rs index 22f6005d3b96..57e1bfb488e1 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs @@ -3191,7 +3191,10 @@ impl MachInstEmit for Inst { } } - &Inst::ElfTlsGetAddr { ref symbol } => { + &Inst::ElfTlsGetAddr { ref symbol, rd } => { + let rd = allocs.next_writable(rd); + assert_eq!(xreg(0), rd.to_reg()); + // This is the instruction sequence that GCC emits for ELF GD TLS Relocations in aarch64 // See: https://gcc.godbolt.org/z/KhMh5Gvra diff --git a/cranelift/codegen/src/isa/aarch64/inst/mod.rs b/cranelift/codegen/src/isa/aarch64/inst/mod.rs index 84292a43bc7b..3d55806cf5f4 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/mod.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/mod.rs @@ -1044,8 +1044,8 @@ fn aarch64_get_operands VReg>(inst: &Inst, collector: &mut Operan } &Inst::VirtualSPOffsetAdj { .. } => {} - &Inst::ElfTlsGetAddr { .. } => { - collector.reg_def(Writable::from_reg(regs::xreg(0))); + &Inst::ElfTlsGetAddr { rd, .. } => { + collector.reg_fixed_def(rd, regs::xreg(0)); let mut clobbers = AArch64MachineDeps::get_regs_clobbered_by_call(CallConv::SystemV); clobbers.remove(regs::xreg_preg(0)); collector.reg_clobbers(clobbers); @@ -2710,8 +2710,9 @@ impl Inst { } &Inst::EmitIsland { needed_space } => format!("emit_island {}", needed_space), - &Inst::ElfTlsGetAddr { ref symbol } => { - format!("x0 = elf_tls_get_addr {}", symbol.display(None)) + &Inst::ElfTlsGetAddr { ref symbol, rd } => { + let rd = pretty_print_reg(rd.to_reg(), allocs); + format!("elf_tls_get_addr {}, {}", rd, symbol.display(None)) } &Inst::Unwind { ref inst } => { format!("unwind {:?}", inst) diff --git a/cranelift/codegen/src/isa/aarch64/lower.isle b/cranelift/codegen/src/isa/aarch64/lower.isle index 3ea1a32f05a4..b0bb4e6f1cd2 100644 --- a/cranelift/codegen/src/isa/aarch64/lower.isle +++ b/cranelift/codegen/src/isa/aarch64/lower.isle @@ -2364,7 +2364,9 @@ ;;; Rules for `tls_value` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; TODO. +(rule (lower (tls_value (symbol_value_data name _ _))) + (if (tls_model_is_elf_gd)) + (elf_tls_get_addr name)) ;;; Rules for `fcvt_low_from_sint` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/cranelift/codegen/src/isa/aarch64/lower_inst.rs b/cranelift/codegen/src/isa/aarch64/lower_inst.rs index 320ea062457a..00953cd77875 100644 --- a/cranelift/codegen/src/isa/aarch64/lower_inst.rs +++ b/cranelift/codegen/src/isa/aarch64/lower_inst.rs @@ -9,7 +9,7 @@ use crate::isa::aarch64::inst::*; use crate::isa::aarch64::settings as aarch64_settings; use crate::machinst::lower::*; use crate::machinst::*; -use crate::settings::{Flags, TlsModel}; +use crate::settings::Flags; use crate::{CodegenError, CodegenResult}; use alloc::boxed::Box; use alloc::vec::Vec; @@ -459,23 +459,7 @@ pub(crate) fn lower_insn_to_regs( implemented_in_isle(ctx) } - Opcode::TlsValue => match flags.tls_model() { - TlsModel::ElfGd => { - let dst = get_output_reg(ctx, outputs[0]).only_reg().unwrap(); - let (name, _, _) = ctx.symbol_value(insn).unwrap(); - let symbol = name.clone(); - ctx.emit(Inst::ElfTlsGetAddr { symbol }); - - let x0 = xreg(0); - ctx.emit(Inst::gen_move(dst, x0, I64)); - } - _ => { - return Err(CodegenError::Unsupported(format!( - "Unimplemented TLS model in AArch64 backend: {:?}", - flags.tls_model() - ))); - } - }, + Opcode::TlsValue => implemented_in_isle(ctx), Opcode::SqmulRoundSat => implemented_in_isle(ctx), diff --git a/cranelift/codegen/src/machinst/lower.rs b/cranelift/codegen/src/machinst/lower.rs index eec970d87b9a..caa5afe2df7e 100644 --- a/cranelift/codegen/src/machinst/lower.rs +++ b/cranelift/codegen/src/machinst/lower.rs @@ -1026,20 +1026,6 @@ impl<'func, I: VCodeInst> Lower<'func, I> { &self.f.dfg[ir_inst] } - /// Get the symbol name, relocation distance estimate, and offset for a - /// symbol_value instruction. - pub fn symbol_value<'b>( - &'b self, - ir_inst: Inst, - ) -> Option<(&'b ExternalName, RelocDistance, i64)> { - match &self.f.dfg[ir_inst] { - &InstructionData::UnaryGlobalValue { global_value, .. } => { - self.symbol_value_data(global_value) - } - _ => None, - } - } - /// Likewise, but starting with a GlobalValue identifier. pub fn symbol_value_data<'b>( &'b self, diff --git a/cranelift/filetests/filetests/isa/aarch64/tls-elf-gd.clif b/cranelift/filetests/filetests/isa/aarch64/tls-elf-gd.clif index 11f87179df4f..016a62450710 100644 --- a/cranelift/filetests/filetests/isa/aarch64/tls-elf-gd.clif +++ b/cranelift/filetests/filetests/isa/aarch64/tls-elf-gd.clif @@ -19,7 +19,7 @@ block0(v0: i32): ; stp d8, d9, [sp, #-16]! ; block0: ; mov x25, x0 -; x0 = elf_tls_get_addr userextname0 +; elf_tls_get_addr x0, userextname0 ; mov x1, x0 ; mov x0, x25 ; ldp d8, d9, [sp], #16