Skip to content

Commit

Permalink
[machinst x64]: add source locations to more instruction formats
Browse files Browse the repository at this point in the history
In order to register traps for `load_splat`, several instruction formats need knowledge of `SourceLoc`s; however, since the x64 backend does not correctly and completely register traps for `RegMem::Mem` variants I opened #2290 to discuss and resolve this issue. In the meantime, the current behavior (i.e. remaining largely unaware of `SourceLoc`s) is retained.
  • Loading branch information
abrown committed Oct 13, 2020
1 parent d99bfa9 commit c9c8de6
Show file tree
Hide file tree
Showing 4 changed files with 262 additions and 122 deletions.
42 changes: 30 additions & 12 deletions cranelift/codegen/src/isa/x64/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1728,6 +1728,7 @@ pub(crate) fn emit(
op,
src: src_e,
dst: reg_g,
srcloc,
} => {
let rex = RexFlags::clear_w();
let (prefix, opcode, length) = match op {
Expand Down Expand Up @@ -1817,6 +1818,10 @@ pub(crate) fn emit(
emit_std_reg_reg(sink, prefix, opcode, length, reg_g.to_reg(), *reg_e, rex);
}
RegMem::Mem { addr } => {
if let Some(srcloc) = *srcloc {
// Register the offset at which the actual load instruction starts.
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
}
let addr = &addr.finalize(state);
emit_std_reg_mem(sink, prefix, opcode, length, reg_g.to_reg(), addr, rex);
}
Expand Down Expand Up @@ -1887,7 +1892,7 @@ pub(crate) fn emit(
// and negative zero. These instructions merge the sign bits in that
// case, and are no-ops otherwise.
let op = if *is_min { or_op } else { and_op };
let inst = Inst::xmm_rm_r(op, RegMem::reg(*lhs), *rhs_dst);
let inst = Inst::xmm_rm_r(op, RegMem::reg(*lhs), *rhs_dst, None);
inst.emit(sink, info, state);

let inst = Inst::jmp_known(done);
Expand All @@ -1897,13 +1902,13 @@ pub(crate) fn emit(
// read-only operand: perform an addition between the two operands, which has the
// desired NaN propagation effects.
sink.bind_label(propagate_nan);
let inst = Inst::xmm_rm_r(add_op, RegMem::reg(*lhs), *rhs_dst);
let inst = Inst::xmm_rm_r(add_op, RegMem::reg(*lhs), *rhs_dst, None);
inst.emit(sink, info, state);

one_way_jmp(sink, CC::P, done);

sink.bind_label(do_min_max);
let inst = Inst::xmm_rm_r(min_max_op, RegMem::reg(*lhs), *rhs_dst);
let inst = Inst::xmm_rm_r(min_max_op, RegMem::reg(*lhs), *rhs_dst, None);
inst.emit(sink, info, state);

sink.bind_label(done);
Expand All @@ -1914,7 +1919,8 @@ pub(crate) fn emit(
src,
dst,
imm,
is64: w,
is64,
srcloc,
} => {
let (prefix, opcode, len) = match op {
SseOpcode::Cmpps => (LegacyPrefixes::None, 0x0FC2, 2),
Expand All @@ -1931,7 +1937,7 @@ pub(crate) fn emit(
SseOpcode::Pshufd => (LegacyPrefixes::_66, 0x0F70, 2),
_ => unimplemented!("Opcode {:?} not implemented", op),
};
let rex = if *w {
let rex = if *is64 {
RexFlags::set_w()
} else {
RexFlags::clear_w()
Expand All @@ -1953,6 +1959,10 @@ pub(crate) fn emit(
}
}
RegMem::Mem { addr } => {
if let Some(srcloc) = *srcloc {
// Register the offset at which the actual load instruction starts.
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
}
let addr = &addr.finalize(state);
assert!(
!regs_swapped,
Expand All @@ -1961,7 +1971,7 @@ pub(crate) fn emit(
emit_std_reg_mem(sink, prefix, opcode, len, dst.to_reg(), addr, rex);
}
}
sink.put1(*imm)
sink.put1(*imm);
}

Inst::XmmLoadConstSeq { val, dst, ty } => {
Expand Down Expand Up @@ -2186,7 +2196,7 @@ pub(crate) fn emit(
} else {
SseOpcode::Addss
};
let inst = Inst::xmm_rm_r(add_op, RegMem::reg(dst.to_reg()), *dst);
let inst = Inst::xmm_rm_r(add_op, RegMem::reg(dst.to_reg()), *dst, None);
inst.emit(sink, info, state);

sink.bind_label(done);
Expand Down Expand Up @@ -2293,8 +2303,12 @@ pub(crate) fn emit(
// If the input was positive, saturate to INT_MAX.

// Zero out tmp_xmm.
let inst =
Inst::xmm_rm_r(SseOpcode::Xorpd, RegMem::reg(tmp_xmm.to_reg()), *tmp_xmm);
let inst = Inst::xmm_rm_r(
SseOpcode::Xorpd,
RegMem::reg(tmp_xmm.to_reg()),
*tmp_xmm,
None,
);
inst.emit(sink, info, state);

let inst = Inst::xmm_cmp_rm_r(cmp_op, RegMem::reg(src), tmp_xmm.to_reg());
Expand Down Expand Up @@ -2365,8 +2379,12 @@ pub(crate) fn emit(
sink.bind_label(check_positive);

// Zero out the tmp_xmm register.
let inst =
Inst::xmm_rm_r(SseOpcode::Xorpd, RegMem::reg(tmp_xmm.to_reg()), *tmp_xmm);
let inst = Inst::xmm_rm_r(
SseOpcode::Xorpd,
RegMem::reg(tmp_xmm.to_reg()),
*tmp_xmm,
None,
);
inst.emit(sink, info, state);

let inst = Inst::xmm_cmp_rm_r(cmp_op, RegMem::reg(src), tmp_xmm.to_reg());
Expand Down Expand Up @@ -2520,7 +2538,7 @@ pub(crate) fn emit(

sink.bind_label(handle_large);

let inst = Inst::xmm_rm_r(sub_op, RegMem::reg(tmp_xmm.to_reg()), *src);
let inst = Inst::xmm_rm_r(sub_op, RegMem::reg(tmp_xmm.to_reg()), *src, None);
inst.emit(sink, info, state);

let inst = Inst::xmm_to_gpr(trunc_op, src.to_reg(), *dst, *dst_size);
Expand Down
Loading

0 comments on commit c9c8de6

Please sign in to comment.