From 52c04433684305227445c91b1b4c1e0bbdaf9581 Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Thu, 29 Nov 2018 18:55:49 +0100 Subject: [PATCH] Pass function sig in function_body::translate --- src/function_body.rs | 45 +++++++++++++++++++++++++++++++-------- src/module.rs | 22 ++++++++++++------- src/tests.rs | 5 +++++ src/translate_sections.rs | 31 +++++++++++++++++---------- 4 files changed, 75 insertions(+), 28 deletions(-) diff --git a/src/function_body.rs b/src/function_body.rs index c49699f1b4..213da6ee59 100644 --- a/src/function_body.rs +++ b/src/function_body.rs @@ -1,6 +1,6 @@ use backend::*; use error::Error; -use wasmparser::{FunctionBody, Operator, Type}; +use wasmparser::{FuncType, FunctionBody, Operator, Type}; // TODO: Use own declared `Type` enum. @@ -86,15 +86,21 @@ impl ControlFrame { } } -pub fn translate(session: &mut CodeGenSession, body: &FunctionBody) -> Result<(), Error> { +pub fn translate( + session: &mut CodeGenSession, + func_type: &FuncType, + body: &FunctionBody, +) -> Result<(), Error> { let locals = body.get_locals_reader()?; - // Assume signature is (i32, i32) -> i32 for now. - // TODO: Use a real signature - const ARG_COUNT: u32 = 2; - let return_ty = Type::I32; + let arg_count = func_type.params.len() as u32; + let return_ty = if func_type.returns.len() > 0 { + func_type.returns[0] + } else { + Type::EmptyBlockType + }; - let mut framesize = ARG_COUNT; + let mut framesize = arg_count; for local in locals { let (count, _ty) = local?; framesize += count; @@ -105,7 +111,7 @@ pub fn translate(session: &mut CodeGenSession, body: &FunctionBody) -> Result<() prologue(&mut ctx, framesize); - for arg_pos in 0..ARG_COUNT { + for arg_pos in 0..arg_count { copy_incoming_arg(&mut ctx, arg_pos); } @@ -191,6 +197,13 @@ pub fn translate(session: &mut CodeGenSession, body: &FunctionBody) -> Result<() } restore_stack_depth(&mut ctx, control_frame.outgoing_stack_depth()); + + if control_frames.len() == 0 { + // This is the last control frame. Perform the implicit return here. + if return_ty != Type::EmptyBlockType { + prepare_return_value(&mut ctx); + } + } } Operator::I32Eq => { relop_eq_i32(&mut ctx); @@ -201,12 +214,26 @@ pub fn translate(session: &mut CodeGenSession, body: &FunctionBody) -> Result<() Operator::GetLocal { local_index } => { get_local_i32(&mut ctx, local_index); } + Operator::Call { function_index } => { + // TODO: find out the signature of this function + // this requires to generalize the function types infrasturcture + + // TODO: ensure that this function is locally defined + // We would like to support imported functions at some point + + // TODO: pop arguments and move them in appropriate positions. + // only 6 for now. + + // TODO: jump to the specified position + // this requires us saving function start locations in codegensession. + + panic!() + } _ => { trap(&mut ctx); } } } - prepare_return_value(&mut ctx); epilogue(&mut ctx); Ok(()) diff --git a/src/module.rs b/src/module.rs index 06a6f9bbb5..6a900a2695 100644 --- a/src/module.rs +++ b/src/module.rs @@ -1,7 +1,7 @@ -use std::mem; -use error::Error; -use translate_sections; use backend::TranslatedCodeSection; +use error::Error; +use std::mem; +use translate_sections; use wasmparser::{ModuleReader, SectionCode}; #[derive(Default)] @@ -14,7 +14,10 @@ impl TranslatedModule { // Assume signature is (i32, i32) -> i32 for now. // TODO: Handle generic signatures. pub fn execute_func(&self, func_idx: u32, a: usize, b: usize) -> usize { - let code_section = self.translated_code_section.as_ref().expect("no code section"); + let code_section = self + .translated_code_section + .as_ref() + .expect("no code section"); let start_buf = code_section.func_start(func_idx as usize); unsafe { @@ -34,10 +37,12 @@ pub fn translate(data: &[u8]) -> Result { return Ok(output); } let mut section = reader.read()?; + let mut types = vec![]; + let mut func_ty_indicies = vec![]; if let SectionCode::Type = section.code { - let types = section.get_type_section_reader()?; - translate_sections::type_(types)?; + let types_reader = section.get_type_section_reader()?; + types = translate_sections::type_(types_reader)?; reader.skip_custom_sections()?; if reader.eof() { @@ -59,7 +64,7 @@ pub fn translate(data: &[u8]) -> Result { if let SectionCode::Function = section.code { let functions = section.get_function_section_reader()?; - translate_sections::function(functions)?; + func_ty_indicies = translate_sections::function(functions)?; reader.skip_custom_sections()?; if reader.eof() { @@ -136,7 +141,8 @@ pub fn translate(data: &[u8]) -> Result { if let SectionCode::Code = section.code { let code = section.get_code_section_reader()?; - output.translated_code_section = Some(translate_sections::code(code)?); + output.translated_code_section = + Some(translate_sections::code(code, &types, &func_ty_indicies)?); reader.skip_custom_sections()?; if reader.eof() { diff --git a/src/tests.rs b/src/tests.rs index b6cc91faae..4a505d6983 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -13,6 +13,11 @@ fn execute_wat(wat: &str, a: usize, b: usize) -> usize { translated.execute_func(0, a, b) } +#[test] +fn empty() { + let _ = translate_wat("(module (func))"); +} + #[test] fn adds() { const CASES: &[(usize, usize, usize)] = &[ diff --git a/src/translate_sections.rs b/src/translate_sections.rs index df2936fdbe..db97713a7a 100644 --- a/src/translate_sections.rs +++ b/src/translate_sections.rs @@ -1,3 +1,4 @@ +use backend::{CodeGenSession, TranslatedCodeSection}; use error::Error; use function_body; #[allow(unused_imports)] // for now @@ -7,14 +8,14 @@ use wasmparser::{ GlobalSectionReader, GlobalType, Import, ImportSectionEntryType, ImportSectionReader, MemorySectionReader, MemoryType, Operator, TableSectionReader, Type, TypeSectionReader, }; -use backend::{CodeGenSession, TranslatedCodeSection}; /// Parses the Type section of the wasm module. -pub fn type_(types: TypeSectionReader) -> Result<(), Error> { - for entry in types { - entry?; // TODO +pub fn type_(types_reader: TypeSectionReader) -> Result, Error> { + let mut types = vec![]; + for entry in types_reader { + types.push(entry?); } - Ok(()) + Ok(types) } /// Parses the Import section of the wasm module. @@ -26,11 +27,12 @@ pub fn import(imports: ImportSectionReader) -> Result<(), Error> { } /// Parses the Function section of the wasm module. -pub fn function(functions: FunctionSectionReader) -> Result<(), Error> { +pub fn function(functions: FunctionSectionReader) -> Result, Error> { + let mut func_ty_indicies = vec![]; for entry in functions { - entry?; // TODO + func_ty_indicies.push(entry?); } - Ok(()) + Ok(func_ty_indicies) } /// Parses the Table section of the wasm module. @@ -80,10 +82,17 @@ pub fn element(elements: ElementSectionReader) -> Result<(), Error> { } /// Parses the Code section of the wasm module. -pub fn code(code: CodeSectionReader) -> Result { +pub fn code( + code: CodeSectionReader, + types: &[FuncType], + func_ty_indicies: &[u32], +) -> Result { let mut session = CodeGenSession::new(); - for body in code { - function_body::translate(&mut session, &body?)?; + for (idx, body) in code.into_iter().enumerate() { + let func_ty_idx = func_ty_indicies[idx]; + let func_ty = &types[func_ty_idx as usize]; + + function_body::translate(&mut session, &func_ty, &body?)?; } Ok(session.into_translated_code_section()?) }