wasmer/lib/llvm-backend/src/state.rs

153 lines
4.2 KiB
Rust
Raw Normal View History

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-12 03:34:04 +00:00
pub enum ControlFrame {
2019-02-09 23:53:40 +00:00
Block {
2019-02-12 03:34:04 +00:00
end_label: BasicBlock,
phis: SmallVec<[PhiValue; 1]>,
2019-02-09 23:53:40 +00:00
stack_size_snapshot: usize,
},
}
2019-02-12 03:34:04 +00:00
impl ControlFrame {
pub fn dest(&self) -> &BasicBlock {
match self {
ControlFrame::Block { ref end_label, .. } => end_label,
}
}
pub fn phis(&self) -> &[PhiValue] {
match self {
ControlFrame::Block { ref phis, .. } => phis.as_slice(),
}
}
}
2019-02-09 23:53:40 +00:00
pub struct State {
stack: Vec<BasicValueEnum>,
control_stack: Vec<ControlFrame>,
2019-02-12 03:34:04 +00:00
value_counter: Cell<usize>,
block_counter: Cell<usize>,
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),
block_counter: Cell::new(0),
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,
..
} => *stack_size_snapshot,
};
self.stack.truncate(stack_size_snapshot);
}
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,
})
}
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 block_name(&self) -> String {
let counter = self.block_counter.get();
let s = format!("block{}", counter);
self.block_counter.set(counter + 1);
s
}
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,
})
}
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-12 03:34:04 +00:00
pub fn push_block(&mut self, end_label: BasicBlock, phis: SmallVec<[PhiValue; 1]>) {
2019-02-09 23:53:40 +00:00
self.control_stack.push(ControlFrame::Block {
2019-02-12 03:34:04 +00:00
end_label,
phis,
2019-02-09 23:53:40 +00:00
stack_size_snapshot: self.stack.len(),
});
}
}