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:
@@ -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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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)",
|
||||||
|
|||||||
@@ -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 { .. } => {}
|
||||||
|
|||||||
Reference in New Issue
Block a user