This commit is contained in:
Sergey Pepyakin 2018-06-13 12:05:20 +03:00
parent d0e13db6f2
commit 5e20cc28f8
3 changed files with 74 additions and 9 deletions

View File

@ -40,7 +40,7 @@
//! - Reserved immediates are ignored for `call_indirect`, `current_memory`, `grow_memory`. //! - Reserved immediates are ignored for `call_indirect`, `current_memory`, `grow_memory`.
//! //!
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct Target { pub struct Target {
pub dst_pc: u32, pub dst_pc: u32,
pub drop: u32, pub drop: u32,
@ -48,7 +48,7 @@ pub struct Target {
} }
#[allow(unused)] // TODO: Remove #[allow(unused)] // TODO: Remove
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
pub enum Instruction { pub enum Instruction {
/// Push a local variable or an argument from the specified depth. /// Push a local variable or an argument from the specified depth.
GetLocal(u32), GetLocal(u32),

View File

@ -109,19 +109,14 @@ impl Validator {
context.push_label(BlockFrameType::Function, result_ty, func_label)?; context.push_label(BlockFrameType::Function, result_ty, func_label)?;
Validator::validate_function_block(&mut context, body.code().elements())?; Validator::validate_function_block(&mut context, body.code().elements())?;
while !context.frame_stack.is_empty() { while !context.frame_stack.is_empty() {
let branch_label = context.top_label()?.branch_label; let branch_label = context.top_label()?.branch_label;
context.sink.resolve_label(branch_label); context.sink.resolve_label(branch_label);
} }
// Emit explicit return.
// let (drop, keep) = context.drop_keep_return()?;
// TODO:
context.sink.emit(isa::Instruction::Return { context.sink.emit(isa::Instruction::Return {
drop: 0, drop: 0,
keep: 0, keep: if result_ty == BlockType::NoResult { 0 } else { 1 },
}); });
Ok(context.into_code()) Ok(context.into_code())

View File

@ -2,8 +2,11 @@ use super::validate_module;
use parity_wasm::builder::module; use parity_wasm::builder::module;
use parity_wasm::elements::{ use parity_wasm::elements::{
External, GlobalEntry, GlobalType, ImportEntry, InitExpr, MemoryType, External, GlobalEntry, GlobalType, ImportEntry, InitExpr, MemoryType,
Opcode, Opcodes, TableType, ValueType, BlockType Opcode, Opcodes, TableType, ValueType, BlockType, deserialize_buffer,
Module,
}; };
use isa;
use wabt;
#[test] #[test]
fn empty_is_valid() { fn empty_is_valid() {
@ -299,3 +302,70 @@ fn if_else_with_return_type_validation() {
.build(); .build();
validate_module(m).unwrap(); validate_module(m).unwrap();
} }
fn compile(wat: &str) -> Vec<isa::Instruction> {
let wasm = wabt::wat2wasm(wat).unwrap();
let module = deserialize_buffer::<Module>(&wasm).unwrap();
let validated_module = validate_module(module).unwrap();
let code = &validated_module.code_map[0];
code.code.clone()
}
#[test]
fn explicit_return_no_value() {
let code = compile(r#"
(module
(func (export "call")
)
)
"#);
assert_eq!(
code,
vec![
isa::Instruction::Return {
drop: 0,
keep: 0,
}
]
)
}
#[test]
fn explicit_return_with_value() {
let code = compile(r#"
(module
(func (export "call") (result i32)
i32.const 0
)
)
"#);
assert_eq!(
code,
vec![
isa::Instruction::I32Const(0),
isa::Instruction::Return {
drop: 0,
keep: 1,
}
]
)
}
#[test]
fn explicit_return_param() {
let code = compile(r#"
(module
(func (export "call") (param i32)
)
)
"#);
assert_eq!(
code,
vec![
isa::Instruction::Return {
drop: 1,
keep: 0,
}
]
)
}