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:
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user