mirror of
https://github.com/Noratrieb/brainfuck.git
synced 2026-01-14 13:35:00 +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 {
|
pub enum Stmt {
|
||||||
Add(u8),
|
Add(u8),
|
||||||
Sub(u8),
|
Sub(u8),
|
||||||
AddOffset(i32, u8),
|
AddOffset { offset: i32, n: u8 },
|
||||||
SubOffset(i32, u8),
|
SubOffset { offset: i32, n: u8 },
|
||||||
|
MoveAddTo { offset: i32 },
|
||||||
Right(u32),
|
Right(u32),
|
||||||
Left(u32),
|
Left(u32),
|
||||||
Out,
|
Out,
|
||||||
|
|
@ -88,8 +89,15 @@ fn ir_to_stmt<'c>(code: &mut Code<'c>, ir_stmt: &IrStmt<'_>) {
|
||||||
let stmt = match &ir_stmt.kind {
|
let stmt = match &ir_stmt.kind {
|
||||||
StmtKind::Add(n) => Stmt::Add(*n),
|
StmtKind::Add(n) => Stmt::Add(*n),
|
||||||
StmtKind::Sub(n) => Stmt::Sub(*n),
|
StmtKind::Sub(n) => Stmt::Sub(*n),
|
||||||
StmtKind::AddOffset(o, n) => Stmt::AddOffset(*o, *n),
|
StmtKind::AddOffset { offset, n } => Stmt::AddOffset {
|
||||||
StmtKind::SubOffset(o, n) => Stmt::SubOffset(*o, *n),
|
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::Right(n) => Stmt::Right(u32::try_from(*n).unwrap()),
|
||||||
StmtKind::Left(n) => Stmt::Left(u32::try_from(*n).unwrap()),
|
StmtKind::Left(n) => Stmt::Left(u32::try_from(*n).unwrap()),
|
||||||
StmtKind::Out => Stmt::Out,
|
StmtKind::Out => Stmt::Out,
|
||||||
|
|
|
||||||
|
|
@ -62,16 +62,13 @@ where
|
||||||
Stmt::Sub(n) => {
|
Stmt::Sub(n) => {
|
||||||
*self.elem_mut() -= n;
|
*self.elem_mut() -= n;
|
||||||
}
|
}
|
||||||
Stmt::AddOffset(o, n) => unsafe {
|
Stmt::AddOffset { offset, n } => *self.elem_mut_offset(offset) += n,
|
||||||
*self
|
Stmt::SubOffset { offset, n } => *self.elem_mut_offset(offset) -= n,
|
||||||
.mem
|
Stmt::MoveAddTo { offset } => {
|
||||||
.get_unchecked_mut((self.ptr as isize + (o as isize)) as usize) += n;
|
let value = self.elem();
|
||||||
},
|
*self.elem_mut() = Wrapping(0);
|
||||||
Stmt::SubOffset(o, n) => unsafe {
|
*self.elem_mut_offset(offset) += value;
|
||||||
*self
|
}
|
||||||
.mem
|
|
||||||
.get_unchecked_mut((self.ptr as isize + (o as isize)) as usize) -= n;
|
|
||||||
},
|
|
||||||
Stmt::Right(n) => {
|
Stmt::Right(n) => {
|
||||||
self.ptr += n as usize;
|
self.ptr += n as usize;
|
||||||
if self.ptr >= MEM_SIZE {
|
if self.ptr >= MEM_SIZE {
|
||||||
|
|
@ -116,15 +113,24 @@ where
|
||||||
(self.profile_collector)(self.ip);
|
(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> {
|
fn elem_mut(&mut self) -> &mut Wrapping<u8> {
|
||||||
// SAFETY: `self.ptr` is never out of bounds
|
// 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) }
|
unsafe { self.mem.get_unchecked_mut(self.ptr) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn elem(&self) -> u8 {
|
fn elem(&self) -> u8 {
|
||||||
// SAFETY: `self.ptr` is never out of bounds
|
// 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 }
|
unsafe { self.mem.get_unchecked(self.ptr).0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,20 @@ impl Debug for Stmt<'_> {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum StmtKind<'ir> {
|
pub enum StmtKind<'ir> {
|
||||||
Add(u8),
|
Add(u8), // todo: we probably want to remove this
|
||||||
Sub(u8),
|
Sub(u8), // todo: we probably want to remove this
|
||||||
AddOffset(i32, u8),
|
AddOffset {
|
||||||
SubOffset(i32, u8),
|
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),
|
Right(usize),
|
||||||
Left(usize),
|
Left(usize),
|
||||||
Loop(Ir<'ir>),
|
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_set_n(&mut ir);
|
||||||
pass_cancel_left_right_add_sub(&mut ir);
|
pass_cancel_left_right_add_sub(&mut ir);
|
||||||
pass_add_sub_offset(&mut ir);
|
pass_add_sub_offset(&mut ir);
|
||||||
|
pass_move_add_to(&mut ir);
|
||||||
ir
|
ir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,22 +230,67 @@ fn pass_add_sub_offset(ir: &mut Ir<'_>) {
|
||||||
window_pass(ir, pass_add_sub_offset, |[a, b, c]| {
|
window_pass(ir, pass_add_sub_offset, |[a, b, c]| {
|
||||||
match (a.kind(), b.kind(), c.kind()) {
|
match (a.kind(), b.kind(), c.kind()) {
|
||||||
(StmtKind::Right(r), StmtKind::Add(n), StmtKind::Left(l)) if r == l => {
|
(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 => {
|
(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 => {
|
(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 => {
|
(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,
|
_ => 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> {
|
enum WindowPassAction<'ir> {
|
||||||
None,
|
None,
|
||||||
Merge(StmtKind<'ir>),
|
Merge(StmtKind<'ir>),
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
<<<<->>>>
|
[->>>>>>>>>+<<<<<<<<<]
|
||||||
Loading…
Add table
Add a link
Reference in a new issue