Add ELF TLS support in new x64 backend.
This follows the implementation in the legacy x86 backend, including hardcoded sequence that is compatible with what the linker expects. We could potentially do better here, but it is likely not necessary. Thanks to @bjorn3 for a bugfix to an earlier version of this.
This commit is contained in:
@@ -2,7 +2,9 @@
|
||||
|
||||
use crate::binemit::{CodeOffset, StackMap};
|
||||
use crate::ir::{types, ExternalName, Opcode, SourceLoc, TrapCode, Type};
|
||||
use crate::isa::x64::abi::X64ABIMachineSpec;
|
||||
use crate::isa::x64::settings as x64_settings;
|
||||
use crate::isa::CallConv;
|
||||
use crate::machinst::*;
|
||||
use crate::{settings, settings::Flags, CodegenError, CodegenResult};
|
||||
use alloc::boxed::Box;
|
||||
@@ -474,6 +476,10 @@ pub enum Inst {
|
||||
/// reports its own `def`s/`use`s/`mod`s; this adds complexity (the instruction list is no
|
||||
/// longer flat) and requires knowledge about semantics and initial-value independence anyway.
|
||||
XmmUninitializedValue { dst: Writable<Reg> },
|
||||
|
||||
/// A call to the `ElfTlsGetAddr` libcall. Returns address
|
||||
/// of TLS symbol in rax.
|
||||
ElfTlsGetAddr { symbol: ExternalName },
|
||||
}
|
||||
|
||||
pub(crate) fn low32_will_sign_extend_to_64(x: u64) -> bool {
|
||||
@@ -532,7 +538,8 @@ impl Inst {
|
||||
| Inst::XmmCmpRmR { .. }
|
||||
| Inst::XmmLoadConst { .. }
|
||||
| Inst::XmmMinMaxSeq { .. }
|
||||
| Inst::XmmUninitializedValue { .. } => None,
|
||||
| Inst::XmmUninitializedValue { .. }
|
||||
| Inst::ElfTlsGetAddr { .. } => None,
|
||||
|
||||
// These use dynamic SSE opcodes.
|
||||
Inst::GprToXmm { op, .. }
|
||||
@@ -1780,6 +1787,10 @@ impl PrettyPrint for Inst {
|
||||
Inst::Hlt => "hlt".into(),
|
||||
|
||||
Inst::Ud2 { trap_code } => format!("ud2 {}", trap_code),
|
||||
|
||||
Inst::ElfTlsGetAddr { ref symbol } => {
|
||||
format!("elf_tls_get_addr {:?}", symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2039,6 +2050,18 @@ fn x64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
|
||||
| Inst::Fence { .. } => {
|
||||
// No registers are used.
|
||||
}
|
||||
|
||||
Inst::ElfTlsGetAddr { .. } => {
|
||||
// All caller-saves are clobbered.
|
||||
//
|
||||
// We use the SysV calling convention here because the
|
||||
// pseudoinstruction (and relocation that it emits) is specific to
|
||||
// ELF systems; other x86-64 targets with other conventions (i.e.,
|
||||
// Windows) use different TLS strategies.
|
||||
for reg in X64ABIMachineSpec::get_regs_clobbered_by_call(CallConv::SystemV) {
|
||||
collector.add_def(reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2425,6 +2448,7 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
|
||||
| Inst::Ud2 { .. }
|
||||
| Inst::Hlt
|
||||
| Inst::AtomicRmwSeq { .. }
|
||||
| Inst::ElfTlsGetAddr { .. }
|
||||
| Inst::Fence { .. } => {
|
||||
// Instruction doesn't explicitly mention any regs, so it can't have any virtual
|
||||
// regs that we'd need to remap. Hence no action required.
|
||||
|
||||
Reference in New Issue
Block a user