codegen: More opcodes

This commit is contained in:
losfair
2019-02-14 00:53:06 +08:00
parent 43df3dd546
commit 7df7204e4b
2 changed files with 49 additions and 2 deletions

View File

@ -2,9 +2,11 @@ use wasmparser::{Operator, Type as WpType};
pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator> {
fn next_function(&mut self) -> Result<&mut FCG, CodegenError>;
fn finalize(&mut self) -> Result<(), CodegenError>;
}
pub trait FunctionCodeGenerator {
fn feed_return(&mut self, ty: WpType) -> Result<(), CodegenError>;
fn feed_param(&mut self, ty: WpType) -> Result<(), CodegenError>;
fn feed_local(&mut self, ty: WpType, n: usize) -> Result<(), CodegenError>;
fn begin_body(&mut self) -> Result<(), CodegenError>;

View File

@ -51,6 +51,7 @@ pub struct X64FunctionCode {
begin_label: DynamicLabel,
cleanup_label: DynamicLabel,
assembler: Option<Assembler>,
returns: Vec<WpType>,
locals: Vec<Local>,
num_params: usize,
current_stack_offset: usize,
@ -94,6 +95,7 @@ impl ModuleCodeGenerator<X64FunctionCode> for X64ModuleCodeGenerator {
begin_label: begin_label,
cleanup_label: assembler.new_dynamic_label(),
assembler: Some(assembler),
returns: vec![],
locals: vec![],
num_params: 0,
current_stack_offset: 0,
@ -102,6 +104,15 @@ impl ModuleCodeGenerator<X64FunctionCode> for X64ModuleCodeGenerator {
self.functions.push(code);
Ok(self.functions.last_mut().unwrap())
}
fn finalize(&mut self) -> Result<(), CodegenError> {
let mut assembler = match self.functions.last_mut() {
Some(x) => x.assembler.take().unwrap(),
None => return Ok(()),
};
let output = assembler.finalize().unwrap();
Ok(())
}
}
impl X64FunctionCode {
@ -121,6 +132,11 @@ impl X64FunctionCode {
}
impl FunctionCodeGenerator for X64FunctionCode {
fn feed_return(&mut self, ty: WpType) -> Result<(), CodegenError> {
self.returns.push(ty);
Ok(())
}
fn feed_param(&mut self, ty: WpType) -> Result<(), CodegenError> {
let assembler = self.assembler.as_mut().unwrap();
let size = get_size_of_type(&ty)?;
@ -246,8 +262,8 @@ impl FunctionCodeGenerator for X64FunctionCode {
message: "I32Add type mismatch",
});
}
Self::gen_rt_pop(assembler, &b);
Self::gen_rt_pop(assembler, &a);
Self::gen_rt_pop(assembler, &b)?;
Self::gen_rt_pop(assembler, &a)?;
self.value_stack.push(WpType::I32);
@ -269,6 +285,35 @@ impl FunctionCodeGenerator for X64FunctionCode {
let info = self.value_stack.pop()?;
Self::gen_rt_pop(assembler, &info)?;
}
Operator::Return => match self.returns.len() {
0 => {}
1 => {
let val = self.value_stack.pop()?;
let ty = self.returns[0];
let reg = val.location.get_register()?;
if is_dword(get_size_of_type(&ty)?) {
dynasm!(
assembler
; mov eax, Rd(Register::from_scratch_reg(reg) as u8)
; jmp =>self.cleanup_label
);
} else {
dynasm!(
assembler
; mov rax, Rq(Register::from_scratch_reg(reg) as u8)
; jmp =>self.cleanup_label
);
}
}
_ => {
return Err(CodegenError {
message: "multiple return values is not yet supported",
})
}
},
Operator::End => {
// todo
}
_ => unimplemented!(),
}
Ok(())