s390x: Implement tls_value (#4616)
Implement the tls_value for s390 in the ELF general-dynamic mode. Notable differences to the x86_64 implementation are: - We use a __tls_get_offset libcall instead of __tls_get_addr. - The current thread pointer (stored in a pair of access registers) needs to be added to the result of __tls_get_offset. - __tls_get_offset has a variant ABI that requires the address of the GOT (global offset table) is passed in %r12. This means we need a new libcall entries for __tls_get_offset. In addition, we also need a way to access _GLOBAL_OFFSET_TABLE_. The latter is a "magic" symbol with a well-known name defined by the ABI and recognized by the linker. This patch introduces a new ExternalName::KnownSymbol variant to support such names (originally due to @afonso360). We also need to emit a relocation on a symbol placed in a constant pool, as well as an extra relocation on the call to __tls_get_offset required for TLS linker optimization. Needed by the cg_clif frontend.
This commit is contained in:
@@ -29,7 +29,7 @@ mod emit_tests;
|
||||
|
||||
pub use crate::isa::s390x::lower::isle::generated_code::{
|
||||
ALUOp, CmpOp, FPUOp1, FPUOp2, FPUOp3, FpuRoundMode, FpuRoundOp, MInst as Inst, RxSBGOp,
|
||||
ShiftOp, UnaryOp, VecBinaryOp, VecFloatCmpOp, VecIntCmpOp, VecShiftOp, VecUnaryOp,
|
||||
ShiftOp, SymbolReloc, UnaryOp, VecBinaryOp, VecFloatCmpOp, VecIntCmpOp, VecShiftOp, VecUnaryOp,
|
||||
};
|
||||
|
||||
/// Additional information for (direct) Call instructions, left out of line to lower the size of
|
||||
@@ -43,6 +43,7 @@ pub struct CallInfo {
|
||||
pub opcode: Opcode,
|
||||
pub caller_callconv: CallConv,
|
||||
pub callee_callconv: CallConv,
|
||||
pub tls_symbol: Option<SymbolReloc>,
|
||||
}
|
||||
|
||||
/// Additional information for CallInd instructions, left out of line to lower the size of the Inst
|
||||
@@ -154,6 +155,8 @@ impl Inst {
|
||||
| Inst::Mov64UImm32Shifted { .. }
|
||||
| Inst::Insert64UImm16Shifted { .. }
|
||||
| Inst::Insert64UImm32Shifted { .. }
|
||||
| Inst::LoadAR { .. }
|
||||
| Inst::InsertAR { .. }
|
||||
| Inst::Extend { .. }
|
||||
| Inst::CMov32 { .. }
|
||||
| Inst::CMov64 { .. }
|
||||
@@ -212,7 +215,7 @@ impl Inst {
|
||||
| Inst::Debugtrap
|
||||
| Inst::Trap { .. }
|
||||
| Inst::JTSequence { .. }
|
||||
| Inst::LoadExtNameFar { .. }
|
||||
| Inst::LoadSymbolReloc { .. }
|
||||
| Inst::LoadAddr { .. }
|
||||
| Inst::Loop { .. }
|
||||
| Inst::CondBreak { .. }
|
||||
@@ -662,6 +665,12 @@ fn s390x_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandC
|
||||
&Inst::Insert64UImm16Shifted { rd, .. } | &Inst::Insert64UImm32Shifted { rd, .. } => {
|
||||
collector.reg_mod(rd);
|
||||
}
|
||||
&Inst::LoadAR { rd, .. } => {
|
||||
collector.reg_def(rd);
|
||||
}
|
||||
&Inst::InsertAR { rd, .. } => {
|
||||
collector.reg_mod(rd);
|
||||
}
|
||||
&Inst::FpuMove32 { rd, rn } | &Inst::FpuMove64 { rd, rn } => {
|
||||
collector.reg_def(rd);
|
||||
collector.reg_use(rn);
|
||||
@@ -881,7 +890,7 @@ fn s390x_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandC
|
||||
collector.reg_use(ridx);
|
||||
collector.reg_early_def(writable_gpr(1));
|
||||
}
|
||||
&Inst::LoadExtNameFar { rd, .. } => {
|
||||
&Inst::LoadSymbolReloc { rd, .. } => {
|
||||
collector.reg_def(rd);
|
||||
collector.reg_def(writable_gpr(1));
|
||||
}
|
||||
@@ -1887,6 +1896,10 @@ impl Inst {
|
||||
};
|
||||
format!("{} {}, {}", op, rd, imm.bits)
|
||||
}
|
||||
&Inst::LoadAR { rd, ar } | &Inst::InsertAR { rd, ar } => {
|
||||
let rd = pretty_print_reg(rd.to_reg(), allocs);
|
||||
format!("ear {}, %a{}", rd, ar)
|
||||
}
|
||||
&Inst::CMov32 { rd, cond, rm } => {
|
||||
let rd = pretty_print_reg(rd.to_reg(), allocs);
|
||||
let rm = pretty_print_reg(rm, allocs);
|
||||
@@ -2830,7 +2843,12 @@ impl Inst {
|
||||
}
|
||||
&Inst::Call { link, ref info, .. } => {
|
||||
let link = pretty_print_reg(link.to_reg(), allocs);
|
||||
format!("brasl {}, {}", link, info.dest)
|
||||
let tls_symbol = match &info.tls_symbol {
|
||||
None => "".to_string(),
|
||||
Some(SymbolReloc::TlsGd { name }) => format!(":tls_gdcall:{}", name),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
format!("brasl {}, {}{}", link, info.dest, tls_symbol)
|
||||
}
|
||||
&Inst::CallInd { link, ref info, .. } => {
|
||||
let link = pretty_print_reg(link.to_reg(), allocs);
|
||||
@@ -2891,17 +2909,17 @@ impl Inst {
|
||||
rtmp, rtmp, rtmp, ridx, rtmp, jt_entries,
|
||||
)
|
||||
}
|
||||
&Inst::LoadExtNameFar {
|
||||
&Inst::LoadSymbolReloc {
|
||||
rd,
|
||||
ref name,
|
||||
offset,
|
||||
ref symbol_reloc,
|
||||
} => {
|
||||
let rd = pretty_print_reg(rd.to_reg(), allocs);
|
||||
let tmp = pretty_print_reg(writable_spilltmp_reg().to_reg(), &mut empty_allocs);
|
||||
format!(
|
||||
"bras {}, 12 ; data {} + {} ; lg {}, 0({})",
|
||||
tmp, name, offset, rd, tmp
|
||||
)
|
||||
let symbol = match &**symbol_reloc {
|
||||
SymbolReloc::Absolute { name, offset } => format!("{} + {}", name, offset),
|
||||
SymbolReloc::TlsGd { name } => format!("{}@tlsgd", name),
|
||||
};
|
||||
format!("bras {}, 12 ; data {} ; lg {}, 0({})", tmp, symbol, rd, tmp)
|
||||
}
|
||||
&Inst::LoadAddr { rd, ref mem } => {
|
||||
let rd = pretty_print_reg(rd.to_reg(), allocs);
|
||||
|
||||
Reference in New Issue
Block a user