diff --git a/lib/dynasm-backend/src/codegen.rs b/lib/dynasm-backend/src/codegen.rs index 1f39e02f2..2695d2435 100644 --- a/lib/dynasm-backend/src/codegen.rs +++ b/lib/dynasm-backend/src/codegen.rs @@ -2,9 +2,11 @@ use wasmparser::{Operator, Type as WpType}; pub trait ModuleCodeGenerator { 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>; diff --git a/lib/dynasm-backend/src/codegen_x64.rs b/lib/dynasm-backend/src/codegen_x64.rs index e7808b0c4..c6f3dc495 100644 --- a/lib/dynasm-backend/src/codegen_x64.rs +++ b/lib/dynasm-backend/src/codegen_x64.rs @@ -51,6 +51,7 @@ pub struct X64FunctionCode { begin_label: DynamicLabel, cleanup_label: DynamicLabel, assembler: Option, + returns: Vec, locals: Vec, num_params: usize, current_stack_offset: usize, @@ -94,6 +95,7 @@ impl ModuleCodeGenerator 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 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(())