diff --git a/cranelift/codegen/src/isa/x64/inst.isle b/cranelift/codegen/src/isa/x64/inst.isle index 792e25d948..316d6e75d8 100644 --- a/cranelift/codegen/src/isa/x64/inst.isle +++ b/cranelift/codegen/src/isa/x64/inst.isle @@ -513,7 +513,8 @@ ;; A Coff TLS symbol access. Returns address of the TLS symbol in ;; `dst`, which is constrained to `rax`. (CoffTlsGetAddr (symbol ExternalName) - (dst WritableGpr)) + (dst WritableGpr) + (tmp WritableGpr)) ;; An unwind pseudoinstruction describing the state of the machine at ;; this program point. @@ -3759,7 +3760,8 @@ (decl coff_tls_get_addr (ExternalName) Gpr) (rule (coff_tls_get_addr name) (let ((dst WritableGpr (temp_writable_gpr)) - (_ Unit (emit (MInst.CoffTlsGetAddr name dst)))) + (tmp WritableGpr (temp_writable_gpr)) + (_ Unit (emit (MInst.CoffTlsGetAddr name dst tmp)))) dst)) ;;;; sqmul_round_sat ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/cranelift/codegen/src/isa/x64/inst/emit.rs b/cranelift/codegen/src/isa/x64/inst/emit.rs index d773ae3816..6b468d2bc6 100644 --- a/cranelift/codegen/src/isa/x64/inst/emit.rs +++ b/cranelift/codegen/src/isa/x64/inst/emit.rs @@ -3195,10 +3195,18 @@ pub(crate) fn emit( sink.put1(0x17); } - Inst::CoffTlsGetAddr { ref symbol, dst } => { + Inst::CoffTlsGetAddr { + ref symbol, + dst, + tmp, + } => { let dst = allocs.next(dst.to_reg().to_reg()); debug_assert_eq!(dst, regs::rax()); + // tmp is used below directly as %rcx + let tmp = allocs.next(tmp.to_reg().to_reg()); + debug_assert_eq!(tmp, regs::rcx()); + // See: https://gcc.godbolt.org/z/M8or9x6ss // And: https://github.com/bjorn3/rustc_codegen_cranelift/issues/388#issuecomment-532930282 diff --git a/cranelift/codegen/src/isa/x64/inst/emit_tests.rs b/cranelift/codegen/src/isa/x64/inst/emit_tests.rs index a56be39f44..4249846a00 100644 --- a/cranelift/codegen/src/isa/x64/inst/emit_tests.rs +++ b/cranelift/codegen/src/isa/x64/inst/emit_tests.rs @@ -4966,6 +4966,7 @@ fn test_x64_emit() { Inst::CoffTlsGetAddr { symbol: ExternalName::User(UserExternalNameRef::new(0)), dst: WritableGpr::from_writable_reg(w_rax).unwrap(), + tmp: WritableGpr::from_writable_reg(w_rcx).unwrap(), }, "8B050000000065488B0C2558000000488B04C1488D8000000000", "%rax = coff_tls_get_addr User(userextname0)", diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs index 34a9df84ae..f9261f1e9e 100644 --- a/cranelift/codegen/src/isa/x64/inst/mod.rs +++ b/cranelift/codegen/src/isa/x64/inst/mod.rs @@ -1655,9 +1655,22 @@ impl PrettyPrint for Inst { format!("{} = macho_tls_get_addr {:?}", dst, symbol) } - Inst::CoffTlsGetAddr { ref symbol, dst } => { + Inst::CoffTlsGetAddr { + ref symbol, + dst, + tmp, + } => { + use std::fmt::Write; + let dst = pretty_print_reg(dst.to_reg().to_reg(), 8, allocs); - format!("{} = coff_tls_get_addr {:?}", dst, symbol) + let tmp = allocs.next(tmp.to_reg().to_reg()); + + let mut s = format!("{} = coff_tls_get_addr {:?}", dst, symbol); + if tmp.is_virtual() { + write!(&mut s, ", {}", show_ireg_sized(tmp, 8)).unwrap(); + }; + + s } Inst::Unwind { inst } => { @@ -2161,7 +2174,7 @@ fn x64_get_operands VReg>(inst: &Inst, collector: &mut OperandCol collector.reg_clobbers(clobbers); } - Inst::CoffTlsGetAddr { dst, .. } => { + Inst::CoffTlsGetAddr { dst, tmp, .. } => { // We also use the gs register. But that register is not allocatable by the // register allocator, so we don't need to mark it as used here. @@ -2169,7 +2182,7 @@ fn x64_get_operands VReg>(inst: &Inst, collector: &mut OperandCol collector.reg_fixed_def(dst.to_writable_reg(), regs::rax()); // We use %rcx as a temporary variable to load the _tls_index - collector.reg_def(Writable::from_reg(regs::rcx())); + collector.reg_fixed_def(tmp.to_writable_reg(), regs::rcx()); } Inst::Unwind { .. } => {}