Don't use %rcx directly with CoffTlsGetAddr (#5278)

Avoid naming %rcx as written by the CoffTlsGetAddr pseudo-instruction in the x64 backend, and instead emit a fixed-def constraint for a fresh VReg and %rcx.
This commit is contained in:
Trevor Elliott
2022-11-16 11:32:09 -08:00
committed by GitHub
parent 5a006674c3
commit 4780bd5902
4 changed files with 31 additions and 7 deletions

View File

@@ -513,7 +513,8 @@
;; A Coff TLS symbol access. Returns address of the TLS symbol in ;; A Coff TLS symbol access. Returns address of the TLS symbol in
;; `dst`, which is constrained to `rax`. ;; `dst`, which is constrained to `rax`.
(CoffTlsGetAddr (symbol ExternalName) (CoffTlsGetAddr (symbol ExternalName)
(dst WritableGpr)) (dst WritableGpr)
(tmp WritableGpr))
;; An unwind pseudoinstruction describing the state of the machine at ;; An unwind pseudoinstruction describing the state of the machine at
;; this program point. ;; this program point.
@@ -3759,7 +3760,8 @@
(decl coff_tls_get_addr (ExternalName) Gpr) (decl coff_tls_get_addr (ExternalName) Gpr)
(rule (coff_tls_get_addr name) (rule (coff_tls_get_addr name)
(let ((dst WritableGpr (temp_writable_gpr)) (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)) dst))
;;;; sqmul_round_sat ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; sqmul_round_sat ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@@ -3195,10 +3195,18 @@ pub(crate) fn emit(
sink.put1(0x17); sink.put1(0x17);
} }
Inst::CoffTlsGetAddr { ref symbol, dst } => { Inst::CoffTlsGetAddr {
ref symbol,
dst,
tmp,
} => {
let dst = allocs.next(dst.to_reg().to_reg()); let dst = allocs.next(dst.to_reg().to_reg());
debug_assert_eq!(dst, regs::rax()); 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 // See: https://gcc.godbolt.org/z/M8or9x6ss
// And: https://github.com/bjorn3/rustc_codegen_cranelift/issues/388#issuecomment-532930282 // And: https://github.com/bjorn3/rustc_codegen_cranelift/issues/388#issuecomment-532930282

View File

@@ -4966,6 +4966,7 @@ fn test_x64_emit() {
Inst::CoffTlsGetAddr { Inst::CoffTlsGetAddr {
symbol: ExternalName::User(UserExternalNameRef::new(0)), symbol: ExternalName::User(UserExternalNameRef::new(0)),
dst: WritableGpr::from_writable_reg(w_rax).unwrap(), dst: WritableGpr::from_writable_reg(w_rax).unwrap(),
tmp: WritableGpr::from_writable_reg(w_rcx).unwrap(),
}, },
"8B050000000065488B0C2558000000488B04C1488D8000000000", "8B050000000065488B0C2558000000488B04C1488D8000000000",
"%rax = coff_tls_get_addr User(userextname0)", "%rax = coff_tls_get_addr User(userextname0)",

View File

@@ -1655,9 +1655,22 @@ impl PrettyPrint for Inst {
format!("{} = macho_tls_get_addr {:?}", dst, symbol) 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); 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 } => { Inst::Unwind { inst } => {
@@ -2161,7 +2174,7 @@ fn x64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandCol
collector.reg_clobbers(clobbers); 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 // 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. // register allocator, so we don't need to mark it as used here.
@@ -2169,7 +2182,7 @@ fn x64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandCol
collector.reg_fixed_def(dst.to_writable_reg(), regs::rax()); collector.reg_fixed_def(dst.to_writable_reg(), regs::rax());
// We use %rcx as a temporary variable to load the _tls_index // 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 { .. } => {} Inst::Unwind { .. } => {}