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:
@@ -2505,149 +2505,148 @@ fn test_aarch64_binemit() {
|
||||
));
|
||||
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
kind: CondBrKind::Zero(xreg(8)),
|
||||
},
|
||||
"080200B4",
|
||||
"cbz x8, 64",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::NotZero(xreg(8)),
|
||||
},
|
||||
"080200B5",
|
||||
"cbnz x8, 64",
|
||||
"480000B40000A0D4",
|
||||
"cbz x8, 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
kind: CondBrKind::Cond(Cond::Eq),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Zero(xreg(8)),
|
||||
},
|
||||
"00020054",
|
||||
"b.eq 64",
|
||||
"480000B50000A0D4",
|
||||
"cbnz x8, 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Ne),
|
||||
},
|
||||
"01020054",
|
||||
"b.ne 64",
|
||||
"400000540000A0D4",
|
||||
"b.eq 8 ; udf",
|
||||
));
|
||||
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
kind: CondBrKind::Cond(Cond::Hs),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Eq),
|
||||
},
|
||||
"02020054",
|
||||
"b.hs 64",
|
||||
"410000540000A0D4",
|
||||
"b.ne 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Lo),
|
||||
},
|
||||
"03020054",
|
||||
"b.lo 64",
|
||||
"420000540000A0D4",
|
||||
"b.hs 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
kind: CondBrKind::Cond(Cond::Mi),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Hs),
|
||||
},
|
||||
"04020054",
|
||||
"b.mi 64",
|
||||
"430000540000A0D4",
|
||||
"b.lo 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Pl),
|
||||
},
|
||||
"05020054",
|
||||
"b.pl 64",
|
||||
"440000540000A0D4",
|
||||
"b.mi 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
kind: CondBrKind::Cond(Cond::Vs),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Mi),
|
||||
},
|
||||
"06020054",
|
||||
"b.vs 64",
|
||||
"450000540000A0D4",
|
||||
"b.pl 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Vc),
|
||||
},
|
||||
"07020054",
|
||||
"b.vc 64",
|
||||
"460000540000A0D4",
|
||||
"b.vs 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
kind: CondBrKind::Cond(Cond::Hi),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Vs),
|
||||
},
|
||||
"08020054",
|
||||
"b.hi 64",
|
||||
"470000540000A0D4",
|
||||
"b.vc 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Ls),
|
||||
},
|
||||
"09020054",
|
||||
"b.ls 64",
|
||||
"480000540000A0D4",
|
||||
"b.hi 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
kind: CondBrKind::Cond(Cond::Ge),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Hi),
|
||||
},
|
||||
"0A020054",
|
||||
"b.ge 64",
|
||||
"490000540000A0D4",
|
||||
"b.ls 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Lt),
|
||||
},
|
||||
"0B020054",
|
||||
"b.lt 64",
|
||||
"4A0000540000A0D4",
|
||||
"b.ge 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
kind: CondBrKind::Cond(Cond::Gt),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Ge),
|
||||
},
|
||||
"0C020054",
|
||||
"b.gt 64",
|
||||
"4B0000540000A0D4",
|
||||
"b.lt 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Le),
|
||||
},
|
||||
"0D020054",
|
||||
"b.le 64",
|
||||
"4C0000540000A0D4",
|
||||
"b.gt 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
kind: CondBrKind::Cond(Cond::Al),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Gt),
|
||||
},
|
||||
"0E020054",
|
||||
"b.al 64",
|
||||
"4D0000540000A0D4",
|
||||
"b.le 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: BranchTarget::ResolvedOffset(64),
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Nv),
|
||||
},
|
||||
"0F020054",
|
||||
"b.nv 64",
|
||||
"4E0000540000A0D4",
|
||||
"b.al 8 ; udf",
|
||||
));
|
||||
insns.push((
|
||||
Inst::TrapIf {
|
||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
||||
kind: CondBrKind::Cond(Cond::Al),
|
||||
},
|
||||
"4F0000540000A0D4",
|
||||
"b.nv 8 ; udf",
|
||||
));
|
||||
|
||||
insns.push((
|
||||
|
||||
Reference in New Issue
Block a user