Skip to content

Commit ebbe626

Browse files
authored
Merge pull request #2685 from cfallin/fix-multi-trap-metadata
Fix incomplete trap metadata due to multiple traps at one address.
2 parents 0cc4a3d + 40db4de commit ebbe626

3 files changed

Lines changed: 108 additions & 17 deletions

File tree

cranelift/codegen/src/isa/x64/inst/emit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ fn emit_std_enc_mem(
232232

233233
let srcloc = state.cur_srcloc();
234234
let can_trap = mem_e.can_trap();
235-
if srcloc != SourceLoc::default() && can_trap {
235+
if can_trap {
236236
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
237237
}
238238

cranelift/codegen/src/isa/x64/lower.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5113,7 +5113,10 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
51135113
));
51145114
ctx.emit(Inst::checked_div_or_rem_seq(kind, size, divisor_copy, tmp));
51155115
} else {
5116-
let divisor = input_to_reg_mem(ctx, inputs[1]);
5116+
// We don't want more than one trap record for a single instruction,
5117+
// so let's not allow the "mem" case (load-op merging) here; force
5118+
// divisor into a register instead.
5119+
let divisor = RegMem::reg(put_input_in_reg(ctx, inputs[1]));
51175120

51185121
// Fill in the high parts:
51195122
if kind.is_signed() {

cranelift/codegen/src/machinst/buffer.rs

Lines changed: 103 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,26 +1314,25 @@ impl MachBufferFinalized {
13141314
let mut next_trap = 0;
13151315
let mut next_call_site = 0;
13161316
for (idx, byte) in self.data.iter().enumerate() {
1317-
if next_reloc < self.relocs.len() {
1317+
while next_reloc < self.relocs.len()
1318+
&& self.relocs[next_reloc].offset == idx as CodeOffset
1319+
{
13181320
let reloc = &self.relocs[next_reloc];
1319-
if reloc.offset == idx as CodeOffset {
1320-
sink.reloc_external(reloc.srcloc, reloc.kind, &reloc.name, reloc.addend);
1321-
next_reloc += 1;
1322-
}
1321+
sink.reloc_external(reloc.srcloc, reloc.kind, &reloc.name, reloc.addend);
1322+
next_reloc += 1;
13231323
}
1324-
if next_trap < self.traps.len() {
1324+
while next_trap < self.traps.len() && self.traps[next_trap].offset == idx as CodeOffset
1325+
{
13251326
let trap = &self.traps[next_trap];
1326-
if trap.offset == idx as CodeOffset {
1327-
sink.trap(trap.code, trap.srcloc);
1328-
next_trap += 1;
1329-
}
1327+
sink.trap(trap.code, trap.srcloc);
1328+
next_trap += 1;
13301329
}
1331-
if next_call_site < self.call_sites.len() {
1330+
while next_call_site < self.call_sites.len()
1331+
&& self.call_sites[next_call_site].ret_addr == idx as CodeOffset
1332+
{
13321333
let call_site = &self.call_sites[next_call_site];
1333-
if call_site.ret_addr == idx as CodeOffset {
1334-
sink.add_call_site(call_site.opcode, call_site.srcloc);
1335-
next_call_site += 1;
1336-
}
1334+
sink.add_call_site(call_site.opcode, call_site.srcloc);
1335+
next_call_site += 1;
13371336
}
13381337
sink.put1(*byte);
13391338
}
@@ -1468,11 +1467,14 @@ impl MachBranch {
14681467
#[cfg(all(test, feature = "arm64"))]
14691468
mod test {
14701469
use super::*;
1470+
use crate::ir::{ConstantOffset, Function, JumpTable, Value};
14711471
use crate::isa::aarch64::inst::xreg;
14721472
use crate::isa::aarch64::inst::{BranchTarget, CondBrKind, EmitInfo, Inst};
1473+
use crate::isa::TargetIsa;
14731474
use crate::machinst::MachInstEmit;
14741475
use crate::settings;
14751476
use std::default::Default;
1477+
use std::vec::Vec;
14761478

14771479
fn label(n: u32) -> MachLabel {
14781480
MachLabel::from_block(n)
@@ -1819,4 +1821,90 @@ mod test {
18191821

18201822
assert_eq!(&golden_data[..], &buf.data[..]);
18211823
}
1824+
1825+
#[test]
1826+
fn metadata_records() {
1827+
let mut buf = MachBuffer::<Inst>::new();
1828+
1829+
buf.reserve_labels_for_blocks(1);
1830+
1831+
buf.bind_label(label(0));
1832+
buf.put1(1);
1833+
buf.add_trap(SourceLoc::default(), TrapCode::HeapOutOfBounds);
1834+
buf.put1(2);
1835+
buf.add_trap(SourceLoc::default(), TrapCode::IntegerOverflow);
1836+
buf.add_trap(SourceLoc::default(), TrapCode::IntegerDivisionByZero);
1837+
buf.add_call_site(SourceLoc::default(), Opcode::Call);
1838+
buf.add_reloc(
1839+
SourceLoc::default(),
1840+
Reloc::Abs4,
1841+
&ExternalName::user(0, 0),
1842+
0,
1843+
);
1844+
buf.put1(3);
1845+
buf.add_reloc(
1846+
SourceLoc::default(),
1847+
Reloc::Abs8,
1848+
&ExternalName::user(1, 1),
1849+
1,
1850+
);
1851+
buf.put1(4);
1852+
1853+
let buf = buf.finish();
1854+
1855+
#[derive(Default)]
1856+
struct TestCodeSink {
1857+
offset: CodeOffset,
1858+
traps: Vec<(CodeOffset, TrapCode)>,
1859+
callsites: Vec<(CodeOffset, Opcode)>,
1860+
relocs: Vec<(CodeOffset, Reloc)>,
1861+
}
1862+
impl CodeSink for TestCodeSink {
1863+
fn offset(&self) -> CodeOffset {
1864+
self.offset
1865+
}
1866+
fn put1(&mut self, _: u8) {
1867+
self.offset += 1;
1868+
}
1869+
fn put2(&mut self, _: u16) {
1870+
self.offset += 2;
1871+
}
1872+
fn put4(&mut self, _: u32) {
1873+
self.offset += 4;
1874+
}
1875+
fn put8(&mut self, _: u64) {
1876+
self.offset += 8;
1877+
}
1878+
fn reloc_external(&mut self, _: SourceLoc, r: Reloc, _: &ExternalName, _: Addend) {
1879+
self.relocs.push((self.offset, r));
1880+
}
1881+
fn reloc_constant(&mut self, _: Reloc, _: ConstantOffset) {}
1882+
fn reloc_jt(&mut self, _: Reloc, _: JumpTable) {}
1883+
fn trap(&mut self, t: TrapCode, _: SourceLoc) {
1884+
self.traps.push((self.offset, t));
1885+
}
1886+
fn begin_jumptables(&mut self) {}
1887+
fn begin_rodata(&mut self) {}
1888+
fn end_codegen(&mut self) {}
1889+
fn add_stack_map(&mut self, _: &[Value], _: &Function, _: &dyn TargetIsa) {}
1890+
fn add_call_site(&mut self, op: Opcode, _: SourceLoc) {
1891+
self.callsites.push((self.offset, op));
1892+
}
1893+
}
1894+
1895+
let mut sink = TestCodeSink::default();
1896+
buf.emit(&mut sink);
1897+
1898+
assert_eq!(sink.offset, 4);
1899+
assert_eq!(
1900+
sink.traps,
1901+
vec![
1902+
(1, TrapCode::HeapOutOfBounds),
1903+
(2, TrapCode::IntegerOverflow),
1904+
(2, TrapCode::IntegerDivisionByZero)
1905+
]
1906+
);
1907+
assert_eq!(sink.callsites, vec![(2, Opcode::Call),]);
1908+
assert_eq!(sink.relocs, vec![(2, Reloc::Abs4), (3, Reloc::Abs8)]);
1909+
}
18221910
}

0 commit comments

Comments
 (0)