AArch64: avoid branches with explicit offsets at lowering stage.

In discussions with @bnjbvr, it came up that generating `OneWayCondBr`s
with explicit, hardcoded PC-offsets as part of lowered instruction
sequences is actually unsafe, because the register allocator *might*
insert a spill or reload into the middle of our sequence. We were
careful about this in some cases but somehow missed that it was a
general restriction. Conceptually, all inter-instruction references
should be via labels at the VCode level; explicit offsets are only ever
known at emission time, and resolved by the `MachBuffer`.

To allow for conditional trap checks without modifying the CFG (as seen
by regalloc) during lowering, this PR instead adds a `TrapIf`
pseudo-instruction that conditionally skips a single embedded trap
instruction. It lowers to the same `condbr label ; trap ; label: ...`
sequence, but without the hardcoded branch-target offset in the lowering
code.
This commit is contained in:
Chris Fallin
2020-07-01 16:28:41 -07:00
parent f2dd1535d5
commit b7ecad1d74
11 changed files with 267 additions and 312 deletions

View File

@@ -1390,7 +1390,9 @@ mod test {
inst.emit(&mut buf, &flags, &mut state);
buf.bind_label(label(1));
let inst = Inst::Nop4;
let inst = Inst::Udf {
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
};
inst.emit(&mut buf, &flags, &mut state);
buf.bind_label(label(2));
@@ -1403,14 +1405,13 @@ mod test {
let mut buf2 = MachBuffer::new();
let mut state = Default::default();
let inst = Inst::OneWayCondBr {
kind: CondBrKind::Zero(xreg(0)),
target: BranchTarget::ResolvedOffset(8),
let inst = Inst::TrapIf {
kind: CondBrKind::NotZero(xreg(0)),
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
};
inst.emit(&mut buf2, &flags, &mut state);
let inst = Inst::Nop4;
inst.emit(&mut buf2, &flags, &mut state);
inst.emit(&mut buf2, &flags, &mut state);
let buf2 = buf2.finish();