mirror of
https://github.com/Noratrieb/brainfuck.git
synced 2026-01-14 21:35:02 +01:00
add pass_move_add_to
This commit is contained in:
parent
014770b6fe
commit
93f97e9a08
4 changed files with 95 additions and 25 deletions
|
|
@ -27,8 +27,9 @@ use std::fmt::{Debug, Formatter};
|
|||
pub enum Stmt {
|
||||
Add(u8),
|
||||
Sub(u8),
|
||||
AddOffset(i32, u8),
|
||||
SubOffset(i32, u8),
|
||||
AddOffset { offset: i32, n: u8 },
|
||||
SubOffset { offset: i32, n: u8 },
|
||||
MoveAddTo { offset: i32 },
|
||||
Right(u32),
|
||||
Left(u32),
|
||||
Out,
|
||||
|
|
@ -88,8 +89,15 @@ fn ir_to_stmt<'c>(code: &mut Code<'c>, ir_stmt: &IrStmt<'_>) {
|
|||
let stmt = match &ir_stmt.kind {
|
||||
StmtKind::Add(n) => Stmt::Add(*n),
|
||||
StmtKind::Sub(n) => Stmt::Sub(*n),
|
||||
StmtKind::AddOffset(o, n) => Stmt::AddOffset(*o, *n),
|
||||
StmtKind::SubOffset(o, n) => Stmt::SubOffset(*o, *n),
|
||||
StmtKind::AddOffset { offset, n } => Stmt::AddOffset {
|
||||
offset: *offset,
|
||||
n: *n,
|
||||
},
|
||||
StmtKind::SubOffset { offset, n } => Stmt::SubOffset {
|
||||
offset: *offset,
|
||||
n: *n,
|
||||
},
|
||||
StmtKind::MoveAddTo { offset } => Stmt::MoveAddTo { offset: *offset },
|
||||
StmtKind::Right(n) => Stmt::Right(u32::try_from(*n).unwrap()),
|
||||
StmtKind::Left(n) => Stmt::Left(u32::try_from(*n).unwrap()),
|
||||
StmtKind::Out => Stmt::Out,
|
||||
|
|
|
|||
|
|
@ -62,16 +62,13 @@ where
|
|||
Stmt::Sub(n) => {
|
||||
*self.elem_mut() -= n;
|
||||
}
|
||||
Stmt::AddOffset(o, n) => unsafe {
|
||||
*self
|
||||
.mem
|
||||
.get_unchecked_mut((self.ptr as isize + (o as isize)) as usize) += n;
|
||||
},
|
||||
Stmt::SubOffset(o, n) => unsafe {
|
||||
*self
|
||||
.mem
|
||||
.get_unchecked_mut((self.ptr as isize + (o as isize)) as usize) -= n;
|
||||
},
|
||||
Stmt::AddOffset { offset, n } => *self.elem_mut_offset(offset) += n,
|
||||
Stmt::SubOffset { offset, n } => *self.elem_mut_offset(offset) -= n,
|
||||
Stmt::MoveAddTo { offset } => {
|
||||
let value = self.elem();
|
||||
*self.elem_mut() = Wrapping(0);
|
||||
*self.elem_mut_offset(offset) += value;
|
||||
}
|
||||
Stmt::Right(n) => {
|
||||
self.ptr += n as usize;
|
||||
if self.ptr >= MEM_SIZE {
|
||||
|
|
@ -116,15 +113,24 @@ where
|
|||
(self.profile_collector)(self.ip);
|
||||
}
|
||||
}
|
||||
|
||||
fn elem_mut_offset(&mut self, offset: i32) -> &mut Wrapping<u8> {
|
||||
let ptr = self.ptr as isize;
|
||||
let offset = offset as isize;
|
||||
// SAFETY: `self.ptr` is never out of bounds
|
||||
debug_assert!(self.ptr < self.mem.len());
|
||||
unsafe { self.mem.get_unchecked_mut((ptr + offset) as usize) }
|
||||
}
|
||||
|
||||
fn elem_mut(&mut self) -> &mut Wrapping<u8> {
|
||||
// SAFETY: `self.ptr` is never out of bounds
|
||||
//debug_assert!(self.ptr < self.mem.len());
|
||||
debug_assert!(self.ptr < self.mem.len());
|
||||
unsafe { self.mem.get_unchecked_mut(self.ptr) }
|
||||
}
|
||||
|
||||
fn elem(&self) -> u8 {
|
||||
// SAFETY: `self.ptr` is never out of bounds
|
||||
//debug_assert!(self.ptr < self.mem.len());
|
||||
debug_assert!(self.ptr < self.mem.len());
|
||||
unsafe { self.mem.get_unchecked(self.ptr).0 }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,10 +40,20 @@ impl Debug for Stmt<'_> {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum StmtKind<'ir> {
|
||||
Add(u8),
|
||||
Sub(u8),
|
||||
AddOffset(i32, u8),
|
||||
SubOffset(i32, u8),
|
||||
Add(u8), // todo: we probably want to remove this
|
||||
Sub(u8), // todo: we probably want to remove this
|
||||
AddOffset {
|
||||
offset: i32,
|
||||
n: u8,
|
||||
},
|
||||
SubOffset {
|
||||
offset: i32,
|
||||
n: u8,
|
||||
},
|
||||
/// Sets the current cell to 0 and adds that value of the cell to another cell at `offset`
|
||||
MoveAddTo {
|
||||
offset: i32,
|
||||
},
|
||||
Right(usize),
|
||||
Left(usize),
|
||||
Loop(Ir<'ir>),
|
||||
|
|
@ -59,6 +69,7 @@ pub fn optimize<'ir>(alloc: &'ir Bump, instrs: &[(Instr<'_>, Span)]) -> Ir<'ir>
|
|||
pass_set_n(&mut ir);
|
||||
pass_cancel_left_right_add_sub(&mut ir);
|
||||
pass_add_sub_offset(&mut ir);
|
||||
pass_move_add_to(&mut ir);
|
||||
ir
|
||||
}
|
||||
|
||||
|
|
@ -219,22 +230,67 @@ fn pass_add_sub_offset(ir: &mut Ir<'_>) {
|
|||
window_pass(ir, pass_add_sub_offset, |[a, b, c]| {
|
||||
match (a.kind(), b.kind(), c.kind()) {
|
||||
(StmtKind::Right(r), StmtKind::Add(n), StmtKind::Left(l)) if r == l => {
|
||||
WindowPassAction::Merge(StmtKind::AddOffset(i32::try_from(*r).unwrap(), *n))
|
||||
WindowPassAction::Merge(StmtKind::AddOffset {
|
||||
offset: i32::try_from(*r).unwrap(),
|
||||
n: *n,
|
||||
})
|
||||
}
|
||||
(StmtKind::Left(l), StmtKind::Add(n), StmtKind::Right(r)) if r == l => {
|
||||
WindowPassAction::Merge(StmtKind::AddOffset(-i32::try_from(*r).unwrap(), *n))
|
||||
WindowPassAction::Merge(StmtKind::AddOffset {
|
||||
offset: -i32::try_from(*r).unwrap(),
|
||||
n: *n,
|
||||
})
|
||||
}
|
||||
(StmtKind::Right(r), StmtKind::Sub(n), StmtKind::Left(l)) if r == l => {
|
||||
WindowPassAction::Merge(StmtKind::SubOffset(i32::try_from(*r).unwrap(), *n))
|
||||
WindowPassAction::Merge(StmtKind::SubOffset {
|
||||
offset: i32::try_from(*r).unwrap(),
|
||||
n: *n,
|
||||
})
|
||||
}
|
||||
(StmtKind::Left(l), StmtKind::Sub(n), StmtKind::Right(r)) if r == l => {
|
||||
WindowPassAction::Merge(StmtKind::SubOffset(-i32::try_from(*r).unwrap(), *n))
|
||||
WindowPassAction::Merge(StmtKind::SubOffset {
|
||||
offset: -i32::try_from(*r).unwrap(),
|
||||
n: *n,
|
||||
})
|
||||
}
|
||||
_ => WindowPassAction::None,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// pass that replaces `Loop([Sub(1) AddOffset(o, 1)])` with `MoveAddTo(o)`
|
||||
#[tracing::instrument]
|
||||
fn pass_move_add_to(ir: &mut Ir<'_>) {
|
||||
for stmt in &mut ir.stmts {
|
||||
if let Stmt {
|
||||
kind: StmtKind::Loop(body),
|
||||
span,
|
||||
} = stmt
|
||||
{
|
||||
if let [Stmt {
|
||||
kind: StmtKind::Sub(1),
|
||||
..
|
||||
}, Stmt {
|
||||
kind: StmtKind::AddOffset { offset, n: 1 },
|
||||
..
|
||||
}]
|
||||
| [Stmt {
|
||||
kind: StmtKind::AddOffset { offset, n: 1 },
|
||||
..
|
||||
}, Stmt {
|
||||
kind: StmtKind::Sub(1),
|
||||
..
|
||||
}] = body.stmts.as_slice()
|
||||
{
|
||||
trace!(?span, ?offset, "Replacing Statement with MoveAddTo");
|
||||
*stmt = Stmt::new(StmtKind::MoveAddTo { offset: *offset }, *span);
|
||||
} else {
|
||||
pass_move_add_to(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum WindowPassAction<'ir> {
|
||||
None,
|
||||
Merge(StmtKind<'ir>),
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
<<<<->>>>
|
||||
[->>>>>>>>>+<<<<<<<<<]
|
||||
Loading…
Add table
Add a link
Reference in a new issue