2019-02-09 23:53:40 +00:00
|
|
|
use inkwell::{
|
|
|
|
basic_block::BasicBlock,
|
2019-02-12 03:34:04 +00:00
|
|
|
values::{BasicValue, BasicValueEnum, PhiValue},
|
2019-02-09 23:53:40 +00:00
|
|
|
};
|
2019-02-12 03:34:04 +00:00
|
|
|
use smallvec::SmallVec;
|
|
|
|
use std::cell::Cell;
|
2019-02-09 23:53:40 +00:00
|
|
|
use wasmparser::BinaryReaderError;
|
|
|
|
|
2019-02-13 02:02:00 +00:00
|
|
|
#[derive(Debug)]
|
2019-02-12 03:34:04 +00:00
|
|
|
pub enum ControlFrame {
|
2019-02-09 23:53:40 +00:00
|
|
|
Block {
|
2019-02-13 02:02:00 +00:00
|
|
|
next: BasicBlock,
|
2019-02-12 03:34:04 +00:00
|
|
|
phis: SmallVec<[PhiValue; 1]>,
|
2019-02-09 23:53:40 +00:00
|
|
|
stack_size_snapshot: usize,
|
|
|
|
},
|
2019-02-13 02:02:00 +00:00
|
|
|
Loop {
|
|
|
|
body: BasicBlock,
|
|
|
|
next: BasicBlock,
|
|
|
|
phis: SmallVec<[PhiValue; 1]>,
|
|
|
|
stack_size_snapshot: usize,
|
|
|
|
},
|
|
|
|
IfElse {
|
|
|
|
if_then: BasicBlock,
|
|
|
|
if_else: BasicBlock,
|
|
|
|
next: BasicBlock,
|
|
|
|
phis: SmallVec<[PhiValue; 1]>,
|
|
|
|
stack_size_snapshot: usize,
|
|
|
|
if_else_state: IfElseState,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum IfElseState {
|
|
|
|
If,
|
|
|
|
Else,
|
2019-02-09 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2019-02-12 03:34:04 +00:00
|
|
|
impl ControlFrame {
|
2019-02-13 02:02:00 +00:00
|
|
|
pub fn code_after(&self) -> &BasicBlock {
|
|
|
|
match self {
|
|
|
|
ControlFrame::Block { ref next, .. }
|
|
|
|
| ControlFrame::Loop { ref next, .. }
|
|
|
|
| ControlFrame::IfElse { ref next, .. } => next,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn br_dest(&self) -> &BasicBlock {
|
2019-02-12 03:34:04 +00:00
|
|
|
match self {
|
2019-02-13 02:02:00 +00:00
|
|
|
ControlFrame::Block { ref next, .. } | ControlFrame::IfElse { ref next, .. } => next,
|
|
|
|
ControlFrame::Loop { ref body, .. } => body,
|
2019-02-12 03:34:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn phis(&self) -> &[PhiValue] {
|
|
|
|
match self {
|
2019-02-13 02:02:00 +00:00
|
|
|
ControlFrame::Block { ref phis, .. }
|
|
|
|
| ControlFrame::Loop { ref phis, .. }
|
|
|
|
| ControlFrame::IfElse { ref phis, .. } => phis.as_slice(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_loop(&self) -> bool {
|
|
|
|
match self {
|
|
|
|
ControlFrame::Loop { .. } => true,
|
|
|
|
_ => false,
|
2019-02-12 03:34:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-13 02:02:00 +00:00
|
|
|
#[derive(Debug)]
|
2019-02-09 23:53:40 +00:00
|
|
|
pub struct State {
|
2019-07-17 18:43:04 +00:00
|
|
|
pub stack: Vec<BasicValueEnum>,
|
2019-02-09 23:53:40 +00:00
|
|
|
control_stack: Vec<ControlFrame>,
|
2019-02-12 03:34:04 +00:00
|
|
|
value_counter: Cell<usize>,
|
2019-02-14 23:13:58 +00:00
|
|
|
|
2019-02-13 02:02:00 +00:00
|
|
|
pub reachable: bool,
|
2019-02-09 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl State {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
stack: vec![],
|
|
|
|
control_stack: vec![],
|
2019-02-12 03:34:04 +00:00
|
|
|
value_counter: Cell::new(0),
|
2019-02-13 02:02:00 +00:00
|
|
|
reachable: true,
|
2019-02-09 23:53:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-12 03:34:04 +00:00
|
|
|
pub fn reset_stack(&mut self, frame: &ControlFrame) {
|
|
|
|
let stack_size_snapshot = match frame {
|
|
|
|
ControlFrame::Block {
|
|
|
|
stack_size_snapshot,
|
|
|
|
..
|
2019-02-13 02:02:00 +00:00
|
|
|
}
|
|
|
|
| ControlFrame::Loop {
|
|
|
|
stack_size_snapshot,
|
|
|
|
..
|
|
|
|
}
|
|
|
|
| ControlFrame::IfElse {
|
|
|
|
stack_size_snapshot,
|
|
|
|
..
|
2019-02-12 03:34:04 +00:00
|
|
|
} => *stack_size_snapshot,
|
|
|
|
};
|
|
|
|
self.stack.truncate(stack_size_snapshot);
|
|
|
|
}
|
|
|
|
|
2019-02-13 02:02:00 +00:00
|
|
|
pub fn outermost_frame(&self) -> Result<&ControlFrame, BinaryReaderError> {
|
|
|
|
self.control_stack.get(0).ok_or(BinaryReaderError {
|
|
|
|
message: "invalid control stack depth",
|
|
|
|
offset: -1isize as usize,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-02-12 03:34:04 +00:00
|
|
|
pub fn frame_at_depth(&self, depth: u32) -> Result<&ControlFrame, BinaryReaderError> {
|
|
|
|
let index = self.control_stack.len() - 1 - (depth as usize);
|
|
|
|
self.control_stack.get(index).ok_or(BinaryReaderError {
|
|
|
|
message: "invalid control stack depth",
|
|
|
|
offset: -1isize as usize,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-02-13 02:02:00 +00:00
|
|
|
pub fn frame_at_depth_mut(
|
|
|
|
&mut self,
|
|
|
|
depth: u32,
|
|
|
|
) -> Result<&mut ControlFrame, BinaryReaderError> {
|
|
|
|
let index = self.control_stack.len() - 1 - (depth as usize);
|
|
|
|
self.control_stack.get_mut(index).ok_or(BinaryReaderError {
|
|
|
|
message: "invalid control stack depth",
|
|
|
|
offset: -1isize as usize,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-02-12 03:34:04 +00:00
|
|
|
pub fn pop_frame(&mut self) -> Result<ControlFrame, BinaryReaderError> {
|
|
|
|
self.control_stack.pop().ok_or(BinaryReaderError {
|
|
|
|
message: "cannot pop from control stack",
|
|
|
|
offset: -1isize as usize,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn var_name(&self) -> String {
|
|
|
|
let counter = self.value_counter.get();
|
|
|
|
let s = format!("s{}", counter);
|
|
|
|
self.value_counter.set(counter + 1);
|
2019-02-09 23:53:40 +00:00
|
|
|
s
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn push1<T: BasicValue>(&mut self, value: T) {
|
|
|
|
self.stack.push(value.as_basic_value_enum())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pop1(&mut self) -> Result<BasicValueEnum, BinaryReaderError> {
|
2019-02-12 03:34:04 +00:00
|
|
|
self.stack.pop().ok_or(BinaryReaderError {
|
2019-02-09 23:53:40 +00:00
|
|
|
message: "invalid value stack",
|
|
|
|
offset: -1isize as usize,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pop2(&mut self) -> Result<(BasicValueEnum, BasicValueEnum), BinaryReaderError> {
|
|
|
|
let v2 = self.pop1()?;
|
|
|
|
let v1 = self.pop1()?;
|
|
|
|
Ok((v1, v2))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pop3(
|
|
|
|
&mut self,
|
|
|
|
) -> Result<(BasicValueEnum, BasicValueEnum, BasicValueEnum), BinaryReaderError> {
|
|
|
|
let v3 = self.pop1()?;
|
|
|
|
let v2 = self.pop1()?;
|
|
|
|
let v1 = self.pop1()?;
|
|
|
|
Ok((v1, v2, v3))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn peek1(&self) -> Result<BasicValueEnum, BinaryReaderError> {
|
|
|
|
self.stack
|
|
|
|
.get(self.stack.len() - 1)
|
2019-02-12 03:34:04 +00:00
|
|
|
.ok_or(BinaryReaderError {
|
2019-02-09 23:53:40 +00:00
|
|
|
message: "invalid value stack",
|
|
|
|
offset: -1isize as usize,
|
|
|
|
})
|
|
|
|
.map(|v| *v)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn peekn(&self, n: usize) -> Result<&[BasicValueEnum], BinaryReaderError> {
|
|
|
|
self.stack
|
|
|
|
.get(self.stack.len() - n..)
|
2019-02-12 03:34:04 +00:00
|
|
|
.ok_or(BinaryReaderError {
|
2019-02-09 23:53:40 +00:00
|
|
|
message: "invalid value stack",
|
|
|
|
offset: -1isize as usize,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-02-13 02:02:00 +00:00
|
|
|
pub fn popn_save(&mut self, n: usize) -> Result<Vec<BasicValueEnum>, BinaryReaderError> {
|
|
|
|
let v = self.peekn(n)?.to_vec();
|
|
|
|
self.popn(n)?;
|
|
|
|
Ok(v)
|
|
|
|
}
|
|
|
|
|
2019-02-09 23:53:40 +00:00
|
|
|
pub fn popn(&mut self, n: usize) -> Result<(), BinaryReaderError> {
|
|
|
|
if self.stack.len() < n {
|
|
|
|
return Err(BinaryReaderError {
|
|
|
|
message: "invalid value stack",
|
|
|
|
offset: -1isize as usize,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
let new_len = self.stack.len() - n;
|
|
|
|
self.stack.truncate(new_len);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2019-02-13 02:02:00 +00:00
|
|
|
pub fn push_block(&mut self, next: BasicBlock, phis: SmallVec<[PhiValue; 1]>) {
|
2019-02-09 23:53:40 +00:00
|
|
|
self.control_stack.push(ControlFrame::Block {
|
2019-02-13 02:02:00 +00:00
|
|
|
next,
|
|
|
|
phis,
|
|
|
|
stack_size_snapshot: self.stack.len(),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn push_loop(&mut self, body: BasicBlock, next: BasicBlock, phis: SmallVec<[PhiValue; 1]>) {
|
|
|
|
self.control_stack.push(ControlFrame::Loop {
|
|
|
|
body,
|
|
|
|
next,
|
|
|
|
phis,
|
|
|
|
stack_size_snapshot: self.stack.len(),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn push_if(
|
|
|
|
&mut self,
|
|
|
|
if_then: BasicBlock,
|
|
|
|
if_else: BasicBlock,
|
|
|
|
next: BasicBlock,
|
|
|
|
phis: SmallVec<[PhiValue; 1]>,
|
|
|
|
) {
|
|
|
|
self.control_stack.push(ControlFrame::IfElse {
|
|
|
|
if_then,
|
|
|
|
if_else,
|
|
|
|
next,
|
2019-02-12 03:34:04 +00:00
|
|
|
phis,
|
2019-02-09 23:53:40 +00:00
|
|
|
stack_size_snapshot: self.stack.len(),
|
2019-02-13 02:02:00 +00:00
|
|
|
if_else_state: IfElseState::If,
|
2019-02-09 23:53:40 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|