Switch to wasmparser's create_binary_reader() API for reading function bodies.

A subtle difference here is that the `end` at the end of a function body
now gets handled by translate_operator/translate_unreachable_operator, so we
no longer have to do as much special-case cleanup at the end of the function
body.

This is a preperatory step for converting module_translator.rs to use
the new FuncTranslator mechanism.
This commit is contained in:
Dan Gohman
2017-09-02 04:14:11 -07:00
parent 25af6d380b
commit f8f6878b2c

View File

@@ -27,7 +27,7 @@ use cretonne::ir::types::*;
use cretonne::ir::immediates::{Ieee32, Ieee64}; use cretonne::ir::immediates::{Ieee32, Ieee64};
use cretonne::ir::condcodes::{IntCC, FloatCC}; use cretonne::ir::condcodes::{IntCC, FloatCC};
use cton_frontend::{ILBuilder, FunctionBuilder}; use cton_frontend::{ILBuilder, FunctionBuilder};
use wasmparser::{Parser, ParserState, Operator, WasmDecoder, MemoryImmediate}; use wasmparser::{Parser, Operator, WasmDecoder, MemoryImmediate};
use translation_utils::{f32_translation, f64_translation, type_to_type, translate_type, Local}; use translation_utils::{f32_translation, f64_translation, type_to_type, translate_type, Local};
use translation_utils::{TableIndex, SignatureIndex, FunctionIndex, MemoryIndex}; use translation_utils::{TableIndex, SignatureIndex, FunctionIndex, MemoryIndex};
use state::{TranslationState, ControlStackFrame}; use state::{TranslationState, ControlStackFrame};
@@ -91,37 +91,15 @@ pub fn translate_function_body(
state.initialize(sig, end_ebb); state.initialize(sig, end_ebb);
// Now the main loop that reads every wasm instruction and translates it // Now the main loop that reads every wasm instruction and translates it
loop { let mut reader = parser.create_binary_reader();
let parser_state = parser.read(); while let Ok(ref op) = reader.read_operator() {
match *parser_state {
ParserState::CodeOperator(ref op) => {
translate_operator(op, &mut builder, &mut state, runtime) translate_operator(op, &mut builder, &mut state, runtime)
} }
debug_assert!(state.control_stack.is_empty());
ParserState::EndFunctionBody => break, debug_assert!(builder.is_pristine());
_ => return Err(String::from("wrong content in function body")),
}
}
// In WebAssembly, the final return instruction is implicit so we need to build it
// explicitely in Cretonne IL.
if !builder.is_filled() && (!builder.is_unreachable() || !builder.is_pristine()) {
let cut_index = state.stack.len() - sig.return_types.len();
builder.ins().return_(&state.stack[cut_index..]);
state.stack.truncate(cut_index);
}
// Because the function has an implicit block as body, we need to explicitely close it.
let frame = state.control_stack.pop().unwrap();
builder.switch_to_block(frame.following_code(), frame.return_values());
builder.seal_block(frame.following_code());
// If the block is reachable we also have to include a return instruction in it.
if !builder.is_unreachable() { if !builder.is_unreachable() {
state.stack.truncate(frame.original_stack_size()); debug_assert!(state.stack.len() == sig.return_types.len());
state.stack.extend_from_slice( builder.ins().return_(&state.stack);
builder.ebb_args(frame.following_code()),
);
let cut_index = state.stack.len() - sig.return_types.len();
builder.ins().return_(&state.stack[cut_index..]);
state.stack.truncate(cut_index);
} }
} }
Ok(func) Ok(func)