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