lint: apply cargo fmt

This commit is contained in:
Igor kehrazy 2026-04-07 17:39:41 +03:00
parent e9858a3eb9
commit 3e7f0e61df
5 changed files with 417 additions and 96 deletions

View file

@ -2,10 +2,7 @@
pub mod arm;
use crate::{
flow::FlowInfo,
ir::Block,
};
use crate::{flow::FlowInfo, ir::Block};
/// Flat generic register metadata.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]

View file

@ -47,7 +47,13 @@ pub struct ArmFeatures {
impl Default for ArmFeatures {
fn default() -> Self {
Self { version: ArmVersion::V7, thumb2: true, vfp: false, neon: false, dsp: false }
Self {
version: ArmVersion::V7,
thumb2: true,
vfp: false,
neon: false,
dsp: false,
}
}
}
@ -143,7 +149,13 @@ impl<'ir, 'fb> ArmLiftCtx<'ir, 'fb> {
for flag in [ArmFlag::N, ArmFlag::Z, ArmFlag::C, ArmFlag::V, ArmFlag::Q] {
fb.declare_var(Self::flag_var(flag), Type::bool());
}
Self { arch, env, fb, pc, mode }
Self {
arch,
env,
fb,
pc,
mode,
}
}
pub fn word_ty(&self) -> Type {
@ -184,22 +196,86 @@ impl<'ir, 'fb> ArmLiftCtx<'ir, 'fb> {
}
pub const REGISTERS: [RegisterDesc<ArmReg>; 16] = [
RegisterDesc { reg: ArmReg::R0, name: "r0", bits: 32 },
RegisterDesc { reg: ArmReg::R1, name: "r1", bits: 32 },
RegisterDesc { reg: ArmReg::R2, name: "r2", bits: 32 },
RegisterDesc { reg: ArmReg::R3, name: "r3", bits: 32 },
RegisterDesc { reg: ArmReg::R4, name: "r4", bits: 32 },
RegisterDesc { reg: ArmReg::R5, name: "r5", bits: 32 },
RegisterDesc { reg: ArmReg::R6, name: "r6", bits: 32 },
RegisterDesc { reg: ArmReg::R7, name: "r7", bits: 32 },
RegisterDesc { reg: ArmReg::R8, name: "r8", bits: 32 },
RegisterDesc { reg: ArmReg::R9, name: "r9", bits: 32 },
RegisterDesc { reg: ArmReg::R10, name: "r10", bits: 32 },
RegisterDesc { reg: ArmReg::R11, name: "r11", bits: 32 },
RegisterDesc { reg: ArmReg::R12, name: "r12", bits: 32 },
RegisterDesc { reg: ArmReg::Sp, name: "sp", bits: 32 },
RegisterDesc { reg: ArmReg::Lr, name: "lr", bits: 32 },
RegisterDesc { reg: ArmReg::Pc, name: "pc", bits: 32 },
RegisterDesc {
reg: ArmReg::R0,
name: "r0",
bits: 32,
},
RegisterDesc {
reg: ArmReg::R1,
name: "r1",
bits: 32,
},
RegisterDesc {
reg: ArmReg::R2,
name: "r2",
bits: 32,
},
RegisterDesc {
reg: ArmReg::R3,
name: "r3",
bits: 32,
},
RegisterDesc {
reg: ArmReg::R4,
name: "r4",
bits: 32,
},
RegisterDesc {
reg: ArmReg::R5,
name: "r5",
bits: 32,
},
RegisterDesc {
reg: ArmReg::R6,
name: "r6",
bits: 32,
},
RegisterDesc {
reg: ArmReg::R7,
name: "r7",
bits: 32,
},
RegisterDesc {
reg: ArmReg::R8,
name: "r8",
bits: 32,
},
RegisterDesc {
reg: ArmReg::R9,
name: "r9",
bits: 32,
},
RegisterDesc {
reg: ArmReg::R10,
name: "r10",
bits: 32,
},
RegisterDesc {
reg: ArmReg::R11,
name: "r11",
bits: 32,
},
RegisterDesc {
reg: ArmReg::R12,
name: "r12",
bits: 32,
},
RegisterDesc {
reg: ArmReg::Sp,
name: "sp",
bits: 32,
},
RegisterDesc {
reg: ArmReg::Lr,
name: "lr",
bits: 32,
},
RegisterDesc {
reg: ArmReg::Pc,
name: "pc",
bits: 32,
},
];
#[derive(Clone, Debug, PartialEq, Eq)]
@ -218,39 +294,52 @@ pub enum ArmLiftError {
/// Map a 4-bit register index to `ArmReg`.
const fn reg_of(r: u8) -> ArmReg {
match r & 0xF {
0 => ArmReg::R0, 1 => ArmReg::R1, 2 => ArmReg::R2, 3 => ArmReg::R3,
4 => ArmReg::R4, 5 => ArmReg::R5, 6 => ArmReg::R6, 7 => ArmReg::R7,
8 => ArmReg::R8, 9 => ArmReg::R9, 10 => ArmReg::R10, 11 => ArmReg::R11,
12 => ArmReg::R12, 13 => ArmReg::Sp, 14 => ArmReg::Lr, _ => ArmReg::Pc,
0 => ArmReg::R0,
1 => ArmReg::R1,
2 => ArmReg::R2,
3 => ArmReg::R3,
4 => ArmReg::R4,
5 => ArmReg::R5,
6 => ArmReg::R6,
7 => ArmReg::R7,
8 => ArmReg::R8,
9 => ArmReg::R9,
10 => ArmReg::R10,
11 => ArmReg::R11,
12 => ArmReg::R12,
13 => ArmReg::Sp,
14 => ArmReg::Lr,
_ => ArmReg::Pc,
}
}
/// Compute a boolean condition value from a 4-bit ARM condition code.
/// Returns `Ok(None)` for AL (always / unconditional).
fn cond_value(
cx: &mut ArmLiftCtx<'_, '_>,
cond: u8,
) -> Result<Option<Value>, ArmLiftError> {
fn cond_value(cx: &mut ArmLiftCtx<'_, '_>, cond: u8) -> Result<Option<Value>, ArmLiftError> {
match cond & 0xF {
0xE => Ok(None), // AL
0x0 => Ok(Some(cx.read_flag(ArmFlag::Z))), // EQ: Z=1
0x1 => { // NE: Z=0
0x1 => {
// NE: Z=0
let z = cx.read_flag(ArmFlag::Z);
Ok(Some(cx.fb.not(z)))
}
0xB => { // LT: N != V — placeholder using N alone
0xB => {
// LT: N != V — placeholder using N alone
Ok(Some(cx.read_flag(ArmFlag::N)))
}
0xA => { // GE: N == V — placeholder using !N alone
0xA => {
// GE: N == V — placeholder using !N alone
let n = cx.read_flag(ArmFlag::N);
Ok(Some(cx.fb.not(n)))
}
0xC => { // GT: Z=0 and N==V — placeholder using Z=0 and N=0
0xC => {
// GT: Z=0 and N==V — placeholder using Z=0 and N=0
let z = cx.read_flag(ArmFlag::Z);
let n = cx.read_flag(ArmFlag::N);
let not_z = cx.fb.not(z);
@ -258,7 +347,8 @@ fn cond_value(
Ok(Some(cx.fb.and(not_z, not_n, Type::bool())))
}
0xD => { // LE: Z=1 or N!=V — placeholder using Z=1 or N=1
0xD => {
// LE: Z=1 or N!=V — placeholder using Z=1 or N=1
let z = cx.read_flag(ArmFlag::Z);
let n = cx.read_flag(ArmFlag::N);
Ok(Some(cx.fb.or(z, n, Type::bool())))
@ -281,9 +371,9 @@ fn apply_shift_imm(
}
let amt = cx.fb.iconst(Type::i32(), imm5 as i64);
Ok(match stype & 3 {
0 => cx.fb.shl(base, amt, Type::i32()), // LSL
1 => cx.fb.lshr(base, amt, Type::i32()), // LSR
2 => cx.fb.ashr(base, amt, Type::i32()), // ASR
0 => cx.fb.shl(base, amt, Type::i32()), // LSL
1 => cx.fb.lshr(base, amt, Type::i32()), // LSR
2 => cx.fb.ashr(base, amt, Type::i32()), // ASR
_ => return Err(ArmLiftError::UnsupportedInstruction), // ROR
})
}
@ -295,18 +385,30 @@ fn addr_imm_off(cx: &mut ArmLiftCtx<'_, '_>, rn: u8, u: bool, imm12: u16) -> Val
return base;
}
let off = cx.fb.iconst(Type::i32(), imm12 as i64);
if u { cx.fb.iadd(base, off, Type::i32()) } else { cx.fb.isub(base, off, Type::i32()) }
if u {
cx.fb.iadd(base, off, Type::i32())
} else {
cx.fb.isub(base, off, Type::i32())
}
}
/// Compute the effective address for an offset-form LDR/STR: base ± shifted rm.
fn addr_reg_off(
cx: &mut ArmLiftCtx<'_, '_>,
rn: u8, u: bool, rm: u8, stype: u8, imm5: u8,
rn: u8,
u: bool,
rm: u8,
stype: u8,
imm5: u8,
) -> Result<Value, ArmLiftError> {
let base = cx.read_reg(reg_of(rn));
let idx_raw = cx.read_reg(reg_of(rm));
let idx = apply_shift_imm(cx, idx_raw, stype, imm5)?;
Ok(if u { cx.fb.iadd(base, idx, Type::i32()) } else { cx.fb.isub(base, idx, Type::i32()) })
Ok(if u {
cx.fb.iadd(base, idx, Type::i32())
} else {
cx.fb.isub(base, idx, Type::i32())
})
}
// ---------------------------------------------------------------------------
@ -319,11 +421,21 @@ impl Arch for Arm {
type Reg = ArmReg;
type DecodeError = A32DecodeError;
fn name(&self) -> &'static str { "arm" }
fn address_size(&self, _mode: Self::Mode) -> u8 { 4 }
fn max_instruction_len(&self) -> u8 { 4 }
fn registers(&self) -> &'static [RegisterDesc<Self::Reg>] { &REGISTERS }
fn stack_pointer(&self) -> Option<Self::Reg> { Some(ArmReg::Sp) }
fn name(&self) -> &'static str {
"arm"
}
fn address_size(&self, _mode: Self::Mode) -> u8 {
4
}
fn max_instruction_len(&self) -> u8 {
4
}
fn registers(&self) -> &'static [RegisterDesc<Self::Reg>] {
&REGISTERS
}
fn stack_pointer(&self) -> Option<Self::Reg> {
Some(ArmReg::Sp)
}
fn decode(
&self,
@ -339,7 +451,8 @@ impl Arch for Arm {
fn flow_info(&self, inst: &Self::Inst, pc: u64, _mode: Self::Mode) -> FlowInfo {
// PC-relative branch offset: target = PC + 8 + (imm24 sign-extended << 2)
let branch_target = |imm24: u32| -> u64 {
pc.wrapping_add(8).wrapping_add_signed(a32_branch_offset(imm24) as i64)
pc.wrapping_add(8)
.wrapping_add_signed(a32_branch_offset(imm24) as i64)
};
match inst {
@ -347,13 +460,22 @@ impl Arch for Arm {
if *rm == 14 {
FlowInfo::new(4, FlowKind::Return)
} else {
FlowInfo::new(4, FlowKind::Jump { target: FlowTarget::Indirect })
FlowInfo::new(
4,
FlowKind::Jump {
target: FlowTarget::Indirect,
},
)
}
}
A32Inst::BlxRA1 { .. } => {
FlowInfo::new(4, FlowKind::Call { target: FlowTarget::Indirect, returns: true })
}
A32Inst::BlxRA1 { .. } => FlowInfo::new(
4,
FlowKind::Call {
target: FlowTarget::Indirect,
returns: true,
},
),
A32Inst::BA1 { cond, imm24 } => {
let target = FlowTarget::Direct(branch_target(*imm24));
@ -366,7 +488,13 @@ impl Arch for Arm {
A32Inst::BlIA1 { imm24, .. } => {
let target = FlowTarget::Direct(branch_target(*imm24));
FlowInfo::new(4, FlowKind::Call { target, returns: true })
FlowInfo::new(
4,
FlowKind::Call {
target,
returns: true,
},
)
}
_ => FlowInfo::new(4, FlowKind::FallThrough),
@ -384,7 +512,8 @@ impl Arch for Arm {
impl LiftArch for Arm {
type LiftError = ArmLiftError;
type LiftCtx<'ir, 'fb> = ArmLiftCtx<'ir, 'fb>
type LiftCtx<'ir, 'fb>
= ArmLiftCtx<'ir, 'fb>
where
Self: 'ir,
'ir: 'fb;
@ -415,7 +544,12 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
}
// MOV wide immediate (MOVW)
A32Inst::MovIA2 { cond, rd, imm12, imm4 } => {
A32Inst::MovIA2 {
cond,
rd,
imm12,
imm4,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -426,8 +560,18 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
}
// ---- MOV register -------------------------------------------------------
A32Inst::MovRA1 { cond, rd, stype, rm }
| A32Inst::MovsRA1 { cond, rd, stype, rm } => {
A32Inst::MovRA1 {
cond,
rd,
stype,
rm,
}
| A32Inst::MovsRA1 {
cond,
rd,
stype,
rm,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -439,8 +583,20 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
}
// ---- ADD register -------------------------------------------------------
A32Inst::AddRA1 { cond, rn, rd, stype, rm }
| A32Inst::AddsRA1 { cond, rn, rd, stype, rm } => {
A32Inst::AddRA1 {
cond,
rn,
rd,
stype,
rm,
}
| A32Inst::AddsRA1 {
cond,
rn,
rd,
stype,
rm,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -453,8 +609,20 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
}
// ---- SUB register -------------------------------------------------------
A32Inst::SubRA1 { cond, rn, rd, stype, rm }
| A32Inst::SubsRA1 { cond, rn, rd, stype, rm } => {
A32Inst::SubRA1 {
cond,
rn,
rd,
stype,
rm,
}
| A32Inst::SubsRA1 {
cond,
rn,
rd,
stype,
rm,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -467,7 +635,12 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
}
// ---- CMP register -------------------------------------------------------
A32Inst::CmpRA1 { cond, rn, stype, rm } => {
A32Inst::CmpRA1 {
cond,
rn,
stype,
rm,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -501,7 +674,13 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
}
// ---- LDR immediate (offset / pre-index / post-index) --------------------
A32Inst::LdrIA1Off { cond, u, rn, rt, imm12 } => {
A32Inst::LdrIA1Off {
cond,
u,
rn,
rt,
imm12,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -511,7 +690,13 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
Ok(())
}
A32Inst::LdrIA1Pre { cond, u, rn, rt, imm12 } => {
A32Inst::LdrIA1Pre {
cond,
u,
rn,
rt,
imm12,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -522,7 +707,13 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
Ok(())
}
A32Inst::LdrIA1Post { cond, u, rn, rt, imm12 } => {
A32Inst::LdrIA1Post {
cond,
u,
rn,
rt,
imm12,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -535,7 +726,15 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
}
// ---- LDR register (offset / pre-index / post-index) ---------------------
A32Inst::LdrRA1Off { cond, u, rn, rt, imm5, stype, rm } => {
A32Inst::LdrRA1Off {
cond,
u,
rn,
rt,
imm5,
stype,
rm,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -545,7 +744,15 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
Ok(())
}
A32Inst::LdrRA1Pre { cond, u, rn, rt, imm5, stype, rm } => {
A32Inst::LdrRA1Pre {
cond,
u,
rn,
rt,
imm5,
stype,
rm,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -556,7 +763,15 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
Ok(())
}
A32Inst::LdrRA1Post { cond, u, rn, rt, imm5, stype, rm } => {
A32Inst::LdrRA1Post {
cond,
u,
rn,
rt,
imm5,
stype,
rm,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -569,7 +784,13 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
}
// ---- STR immediate ------------------------------------------------------
A32Inst::StrIA1Off { cond, u, rn, rt, imm12 } => {
A32Inst::StrIA1Off {
cond,
u,
rn,
rt,
imm12,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -579,7 +800,13 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
Ok(())
}
A32Inst::StrIA1Pre { cond, u, rn, rt, imm12 } => {
A32Inst::StrIA1Pre {
cond,
u,
rn,
rt,
imm12,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -590,7 +817,13 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
Ok(())
}
A32Inst::StrIA1Post { cond, u, rn, rt, imm12 } => {
A32Inst::StrIA1Post {
cond,
u,
rn,
rt,
imm12,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -603,7 +836,15 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
}
// ---- STR register -------------------------------------------------------
A32Inst::StrRA1Off { cond, u, rn, rt, imm5, stype, rm } => {
A32Inst::StrRA1Off {
cond,
u,
rn,
rt,
imm5,
stype,
rm,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -613,7 +854,15 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
Ok(())
}
A32Inst::StrRA1Pre { cond, u, rn, rt, imm5, stype, rm } => {
A32Inst::StrRA1Pre {
cond,
u,
rn,
rt,
imm5,
stype,
rm,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -624,7 +873,15 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
Ok(())
}
A32Inst::StrRA1Post { cond, u, rn, rt, imm5, stype, rm } => {
A32Inst::StrRA1Post {
cond,
u,
rn,
rt,
imm5,
stype,
rm,
} => {
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
@ -638,14 +895,19 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
// ---- B ------------------------------------------------------------------
A32Inst::BA1 { cond, imm24 } => {
let target_addr = cx.pc.wrapping_add(8)
let target_addr = cx
.pc
.wrapping_add(8)
.wrapping_add_signed(a32_branch_offset(*imm24) as i64);
let target_block = cx
.direct_block(target_addr)
.ok_or(ArmLiftError::MissingTargetBlock)?;
match cond_value(cx, *cond)? {
None => { cx.fb.jump(target_block); Ok(()) }
None => {
cx.fb.jump(target_block);
Ok(())
}
Some(c) => {
let fallthrough = cx
.fallthrough_block()
@ -661,7 +923,9 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
if cond_value(cx, *cond)?.is_some() {
return Err(ArmLiftError::UnsupportedCondition);
}
let target_addr = cx.pc.wrapping_add(8)
let target_addr = cx
.pc
.wrapping_add(8)
.wrapping_add_signed(a32_branch_offset(*imm24) as i64);
let callee = cx.fb.iconst(Type::ptr(32), target_addr as i64);
cx.fb.call(callee, &[]);
@ -699,6 +963,10 @@ fn lift_inst(cx: &mut ArmLiftCtx<'_, '_>, inst: &A32Inst) -> Result<(), ArmLiftE
pub struct DummyEnv;
impl LiftEnv for DummyEnv {
fn block_for_target(&self, _addr: u64) -> Option<Block> { None }
fn fallthrough_block(&self) -> Option<Block> { None }
fn block_for_target(&self, _addr: u64) -> Option<Block> {
None
}
fn fallthrough_block(&self) -> Option<Block> {
None
}
}

View file

@ -29,7 +29,6 @@ pub enum StmtData {
// ------------------------------------------------------------------ //
// Value-producing statements //
// ------------------------------------------------------------------ //
/// Signed integer literal. Result type determines the width.
IConst { imm: i64, result: Value },
@ -43,19 +42,42 @@ pub enum StmtData {
BConst { value: bool, result: Value },
/// Unary operation.
Unary { op: UnaryOp, arg: Value, result: Value },
Unary {
op: UnaryOp,
arg: Value,
result: Value,
},
/// Binary operation.
Binary { op: BinaryOp, lhs: Value, rhs: Value, result: Value },
Binary {
op: BinaryOp,
lhs: Value,
rhs: Value,
result: Value,
},
/// Cast or conversion.
Cast { op: CastOp, arg: Value, result: Value },
Cast {
op: CastOp,
arg: Value,
result: Value,
},
/// Integer comparison. Result type is always `bool`.
Icmp { cc: IntCC, lhs: Value, rhs: Value, result: Value },
Icmp {
cc: IntCC,
lhs: Value,
rhs: Value,
result: Value,
},
/// Floating-point comparison. Result type is always `bool`.
Fcmp { cc: FloatCC, lhs: Value, rhs: Value, result: Value },
Fcmp {
cc: FloatCC,
lhs: Value,
rhs: Value,
result: Value,
},
/// Conditional select. `cond` must be `bool`.
Select {
@ -66,14 +88,21 @@ pub enum StmtData {
},
/// Memory load. Anchored in the statement stream to preserve memory order.
Load { addr: Value, size: MemSize, result: Value },
Load {
addr: Value,
size: MemSize,
result: Value,
},
// ------------------------------------------------------------------ //
// Side-effecting statements (no result value) //
// ------------------------------------------------------------------ //
/// Memory store.
Store { addr: Value, value: Value, size: MemSize },
Store {
addr: Value,
value: Value,
size: MemSize,
},
/// Effectful call.
Call { callee: Value, args: ValueList },
@ -81,7 +110,6 @@ pub enum StmtData {
// ------------------------------------------------------------------ //
// Terminators //
// ------------------------------------------------------------------ //
/// Unconditional jump.
Jump { dst: BlockCall },
@ -122,7 +150,10 @@ impl StmtData {
/// Returns whether this statement is a block terminator.
pub const fn is_terminator(self) -> bool {
matches!(self, Self::Jump { .. } | Self::BrIf { .. } | Self::Return { .. })
matches!(
self,
Self::Jump { .. } | Self::BrIf { .. } | Self::Return { .. }
)
}
/// Returns whether this statement may read memory.

View file

@ -143,7 +143,9 @@ impl Verifier<'_> {
self.verify_result(stmt, result)?;
}
StmtData::Binary { lhs, rhs, result, .. } => {
StmtData::Binary {
lhs, rhs, result, ..
} => {
self.ensure_valid_value(lhs, format!("statement {stmt} binary lhs"))?;
self.ensure_valid_value(rhs, format!("statement {stmt} binary rhs"))?;
self.verify_result(stmt, result)?;
@ -154,8 +156,12 @@ impl Verifier<'_> {
self.verify_result(stmt, result)?;
}
StmtData::Icmp { lhs, rhs, result, .. }
| StmtData::Fcmp { lhs, rhs, result, .. } => {
StmtData::Icmp {
lhs, rhs, result, ..
}
| StmtData::Fcmp {
lhs, rhs, result, ..
} => {
self.ensure_valid_value(lhs, format!("statement {stmt} compare lhs"))?;
self.ensure_valid_value(rhs, format!("statement {stmt} compare rhs"))?;
self.verify_result(stmt, result)?;

View file

@ -64,7 +64,11 @@ impl Printer<'_> {
match *self.body.stmt_data(stmt) {
StmtData::IConst { imm, result } => {
writeln!(f, "%{result} = iconst {imm} : {}", self.body.value_type(result))
writeln!(
f,
"%{result} = iconst {imm} : {}",
self.body.value_type(result)
)
}
StmtData::F32Const { bits, result } => {
@ -87,7 +91,12 @@ impl Printer<'_> {
)
}
StmtData::Binary { op, lhs, rhs, result } => {
StmtData::Binary {
op,
lhs,
rhs,
result,
} => {
writeln!(
f,
"%{result} = {op} %{lhs}, %{rhs} : {}",
@ -104,7 +113,12 @@ impl Printer<'_> {
)
}
StmtData::Icmp { cc, lhs, rhs, result } => {
StmtData::Icmp {
cc,
lhs,
rhs,
result,
} => {
writeln!(
f,
"%{result} = icmp {cc} %{lhs}, %{rhs} : {}",
@ -112,7 +126,12 @@ impl Printer<'_> {
)
}
StmtData::Fcmp { cc, lhs, rhs, result } => {
StmtData::Fcmp {
cc,
lhs,
rhs,
result,
} => {
writeln!(
f,
"%{result} = fcmp {cc} %{lhs}, %{rhs} : {}",