Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mis-aligned access issues with s390x #4702

Merged
merged 1 commit into from
Aug 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions cranelift/codegen/src/isa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,15 @@ impl<'a> dyn TargetIsa + 'a {
}
}

/// Returns the minimum symbol alignment for this ISA.
pub fn symbol_alignment(&self) -> u64 {
match self.triple().architecture {
// All symbols need to be aligned to at least 2 on s390x.
Architecture::S390x => 2,
_ => 1,
}
}

/// Get the pointer type of this ISA.
pub fn pointer_type(&self) -> ir::Type {
ir::Type::int(self.pointer_bits() as u16).unwrap()
Expand Down
88 changes: 68 additions & 20 deletions cranelift/codegen/src/isa/s390x/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,28 @@ use crate::trace;
use core::convert::TryFrom;
use regalloc2::Allocation;

/// Type(s) of memory instructions available for mem_finalize.
pub struct MemInstType {
/// True if 12-bit unsigned displacement is supported.
pub have_d12: bool,
/// True if 20-bit signed displacement is supported.
pub have_d20: bool,
/// True if PC-relative addressing is supported (memory access).
pub have_pcrel: bool,
/// True if PC-relative addressing is supported (load address).
pub have_unaligned_pcrel: bool,
/// True if an index register is supported.
pub have_index: bool,
}

/// Memory addressing mode finalization: convert "special" modes (e.g.,
/// generic arbitrary stack offset) into real addressing modes, possibly by
/// emitting some helper instructions that come immediately before the use
/// of this amode.
pub fn mem_finalize(
mem: &MemArg,
state: &EmitState,
have_d12: bool,
have_d20: bool,
have_pcrel: bool,
have_index: bool,
mi: MemInstType,
) -> (SmallVec<[Inst; 4]>, MemArg) {
let mut insts = SmallVec::new();

Expand Down Expand Up @@ -70,9 +81,10 @@ pub fn mem_finalize(

// If this addressing mode cannot be handled by the instruction, use load-address.
let need_load_address = match &mem {
&MemArg::Label { .. } | &MemArg::Symbol { .. } if !have_pcrel => true,
&MemArg::BXD20 { .. } if !have_d20 => true,
&MemArg::BXD12 { index, .. } | &MemArg::BXD20 { index, .. } if !have_index => {
&MemArg::Label { .. } | &MemArg::Symbol { .. } if !mi.have_pcrel => true,
&MemArg::Symbol { flags, .. } if !mi.have_unaligned_pcrel && !flags.aligned() => true,
&MemArg::BXD20 { .. } if !mi.have_d20 => true,
&MemArg::BXD12 { index, .. } | &MemArg::BXD20 { index, .. } if !mi.have_index => {
index != zero_reg()
}
_ => false,
Expand All @@ -93,8 +105,8 @@ pub fn mem_finalize(
index,
disp,
flags,
} if !have_d12 => {
assert!(have_d20);
} if !mi.have_d12 => {
assert!(mi.have_d20);
MemArg::BXD20 {
base,
index,
Expand Down Expand Up @@ -122,10 +134,13 @@ pub fn mem_emit(
let (mem_insts, mem) = mem_finalize(
mem,
state,
opcode_rx.is_some(),
opcode_rxy.is_some(),
opcode_ril.is_some(),
true,
MemInstType {
have_d12: opcode_rx.is_some(),
have_d20: opcode_rxy.is_some(),
have_pcrel: opcode_ril.is_some(),
have_unaligned_pcrel: opcode_ril.is_some() && !add_trap,
have_index: true,
},
);
for inst in mem_insts.into_iter() {
inst.emit(&[], sink, emit_info, state);
Expand Down Expand Up @@ -190,10 +205,13 @@ pub fn mem_rs_emit(
let (mem_insts, mem) = mem_finalize(
mem,
state,
opcode_rs.is_some(),
opcode_rsy.is_some(),
false,
false,
MemInstType {
have_d12: opcode_rs.is_some(),
have_d20: opcode_rsy.is_some(),
have_pcrel: false,
have_unaligned_pcrel: false,
have_index: false,
},
);
for inst in mem_insts.into_iter() {
inst.emit(&[], sink, emit_info, state);
Expand Down Expand Up @@ -236,7 +254,17 @@ pub fn mem_imm8_emit(
emit_info: &EmitInfo,
state: &mut EmitState,
) {
let (mem_insts, mem) = mem_finalize(mem, state, true, true, false, false);
let (mem_insts, mem) = mem_finalize(
mem,
state,
MemInstType {
have_d12: true,
have_d20: true,
have_pcrel: false,
have_unaligned_pcrel: false,
have_index: false,
},
);
for inst in mem_insts.into_iter() {
inst.emit(&[], sink, emit_info, state);
}
Expand Down Expand Up @@ -274,7 +302,17 @@ pub fn mem_imm16_emit(
emit_info: &EmitInfo,
state: &mut EmitState,
) {
let (mem_insts, mem) = mem_finalize(mem, state, true, false, false, false);
let (mem_insts, mem) = mem_finalize(
mem,
state,
MemInstType {
have_d12: true,
have_d20: false,
have_pcrel: false,
have_unaligned_pcrel: false,
have_index: false,
},
);
for inst in mem_insts.into_iter() {
inst.emit(&[], sink, emit_info, state);
}
Expand Down Expand Up @@ -336,7 +374,17 @@ pub fn mem_vrx_emit(
emit_info: &EmitInfo,
state: &mut EmitState,
) {
let (mem_insts, mem) = mem_finalize(mem, state, true, false, false, true);
let (mem_insts, mem) = mem_finalize(
mem,
state,
MemInstType {
have_d12: true,
have_d20: false,
have_pcrel: false,
have_unaligned_pcrel: false,
have_index: true,
},
);
for inst in mem_insts.into_iter() {
inst.emit(&[], sink, emit_info, state);
}
Expand Down
Loading