diff --git a/lib/frontend/src/frontend.rs b/lib/frontend/src/frontend.rs index 376f798dd2..53b33334ea 100644 --- a/lib/frontend/src/frontend.rs +++ b/lib/frontend/src/frontend.rs @@ -129,12 +129,10 @@ impl<'short, 'long, Variable> InstBuilderBase<'short> for FuncInstBuilder<'short // If the user has supplied jump arguments we must adapt the arguments of // the destination ebb // TODO: find a way not to allocate a vector - let args_types: Vec = + let args_types: Vec = match data.analyze_branch(&self.builder.func.dfg.value_lists) { BranchInfo::SingleDest(_, args) => { - args.iter() - .map(|arg| self.builder.func.dfg.value_type(*arg)) - .collect() + args.to_vec() } _ => panic!("should not happen"), }; @@ -255,7 +253,7 @@ where /// When inserting the terminator instruction (which doesn't have a falltrough to its immediate /// successor), the block will be declared filled and it will not be possible to append /// instructions to it. - pub fn switch_to_block(&mut self, ebb: Ebb, jump_args: &[Type]) -> &[Value] { + pub fn switch_to_block(&mut self, ebb: Ebb, jump_args: &[Value]) -> &[Value] { if self.pristine { self.fill_function_args_values(ebb); } @@ -556,7 +554,7 @@ where } - fn ebb_args_adjustment(&mut self, dest_ebb: Ebb, jump_args: &[Type]) { + fn ebb_args_adjustment(&mut self, dest_ebb: Ebb, jump_args: &[Value]) { if self.builder.ssa.predecessors(dest_ebb).is_empty() || self.builder.ebbs[dest_ebb].pristine { @@ -571,7 +569,8 @@ where .iter() .zip(jump_args.iter().take(dest_ebb_args.len())) .all(|(dest_arg, jump_arg)| { - *jump_arg == self.func.dfg.value_type(*dest_arg) + self.func.dfg.value_type(*jump_arg) == + self.func.dfg.value_type(*dest_arg) }), "the jump argument supplied has not the \ same type as the corresponding dest ebb argument" @@ -579,8 +578,9 @@ where dest_ebb_args.len() }; self.builder.ebbs[dest_ebb].user_arg_count = jump_args.len(); - for ty in jump_args.iter().skip(dest_ebb_args_len) { - self.func.dfg.append_ebb_arg(dest_ebb, *ty); + for val in jump_args.iter().skip(dest_ebb_args_len) { + let ty = self.func.dfg.value_type(*val); + self.func.dfg.append_ebb_arg(dest_ebb, ty); } } else { // The Ebb already has predecessors @@ -599,7 +599,7 @@ where self.builder.ebbs[dest_ebb].user_arg_count, )) .all(|(jump_arg, dest_arg)| { - *jump_arg == self.func.dfg.value_type(*dest_arg) + self.func.dfg.value_type(*jump_arg) == self.func.dfg.value_type(*dest_arg) }), "the jump argument supplied has not the \ same type as the corresponding dest ebb argument" diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index 8af0127410..d96deafb0a 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -26,7 +26,7 @@ use cretonne::ir::types::*; use cretonne::ir::condcodes::{IntCC, FloatCC}; use cton_frontend::FunctionBuilder; use wasmparser::{Operator, MemoryImmediate}; -use translation_utils::{f32_translation, f64_translation, type_to_type, translate_type, Local}; +use translation_utils::{f32_translation, f64_translation, type_to_type, num_return_values, Local}; use translation_utils::{TableIndex, SignatureIndex, FunctionIndex, MemoryIndex}; use state::{TranslationState, ControlStackFrame}; use std::collections::HashMap; @@ -122,7 +122,7 @@ pub fn translate_operator( if let Ok(ty_cre) = type_to_type(&ty) { builder.append_ebb_arg(next, ty_cre); } - state.push_block(next, translate_type(ty)); + state.push_block(next, num_return_values(ty)); } Operator::Loop { ty } => { let loop_body = builder.create_ebb(); @@ -131,7 +131,7 @@ pub fn translate_operator( builder.append_ebb_arg(next, ty_cre); } builder.ins().jump(loop_body, &[]); - state.push_loop(loop_body, next, translate_type(ty)); + state.push_loop(loop_body, next, num_return_values(ty)); builder.switch_to_block(loop_body, &[]); } Operator::If { ty } => { @@ -147,7 +147,7 @@ pub fn translate_operator( if let Ok(ty_cre) = type_to_type(&ty) { builder.append_ebb_arg(if_not, ty_cre); } - state.push_if(jump_inst, if_not, translate_type(ty)); + state.push_if(jump_inst, if_not, num_return_values(ty)); } Operator::Else => { // We take the control frame pushed by the if, use its ebb as the else body @@ -157,10 +157,10 @@ pub fn translate_operator( let (destination, return_count, branch_inst) = match state.control_stack[i] { ControlStackFrame::If { destination, - ref return_values, + num_return_values, branch_inst, .. - } => (destination, return_values.len(), branch_inst), + } => (destination, num_return_values, branch_inst), _ => panic!("should not happen"), }; builder.ins().jump(destination, state.peekn(return_count)); @@ -173,15 +173,14 @@ pub fn translate_operator( } Operator::End => { let frame = state.control_stack.pop().unwrap(); + let return_count = frame.num_return_values(); if !builder.is_unreachable() || !builder.is_pristine() { - let return_count = frame.return_values().len(); builder.ins().jump( frame.following_code(), state.peekn(return_count), ); - state.popn(return_count); } - builder.switch_to_block(frame.following_code(), frame.return_values()); + builder.switch_to_block(frame.following_code(), state.peekn(return_count)); builder.seal_block(frame.following_code()); // If it is a loop we also have to seal the body loop block match frame { @@ -223,7 +222,7 @@ pub fn translate_operator( let return_count = if frame.is_loop() { 0 } else { - frame.return_values().len() + frame.num_return_values() }; (return_count, frame.br_destination()) }; @@ -245,7 +244,7 @@ pub fn translate_operator( let return_count = if frame.is_loop() { 0 } else { - frame.return_values().len() + frame.num_return_values() }; (return_count, frame.br_destination()) }; @@ -269,7 +268,7 @@ pub fn translate_operator( if min_depth_frame.is_loop() { 0 } else { - min_depth_frame.return_values().len() + min_depth_frame.num_return_values() } }; if jump_args_count == 0 { @@ -334,7 +333,7 @@ pub fn translate_operator( let (return_count, br_destination) = { let frame = &mut state.control_stack[0]; frame.set_reachable(); - let return_count = frame.return_values().len(); + let return_count = frame.num_return_values(); (return_count, frame.br_destination()) }; { diff --git a/lib/wasm/src/state.rs b/lib/wasm/src/state.rs index 8130b469af..d862e8d9a0 100644 --- a/lib/wasm/src/state.rs +++ b/lib/wasm/src/state.rs @@ -3,7 +3,7 @@ //! The `TranslationState` struct defined in this module is used to keep track of the WebAssembly //! value and control stacks during the translation of a single function. -use cretonne::ir::{self, Ebb, Inst, Type, Value}; +use cretonne::ir::{self, Ebb, Inst, Value}; use runtime::{FuncEnvironment, GlobalValue}; use std::collections::HashMap; use translation_utils::{GlobalIndex, MemoryIndex, SignatureIndex, FunctionIndex}; @@ -12,7 +12,7 @@ use translation_utils::{GlobalIndex, MemoryIndex, SignatureIndex, FunctionIndex} /// fields: /// /// - `destination`: reference to the `Ebb` that will hold the code after the control block; -/// - `return_values`: types of the values returned by the control block; +/// - `num_return_values`: number of values returned by the control block; /// - `original_stack_size`: size of the value stack at the beginning of the control block. /// /// Moreover, the `if` frame has the `branch_inst` field that points to the `brz` instruction @@ -23,20 +23,20 @@ pub enum ControlStackFrame { If { destination: Ebb, branch_inst: Inst, - return_values: Vec, + num_return_values: usize, original_stack_size: usize, reachable: bool, }, Block { destination: Ebb, - return_values: Vec, + num_return_values: usize, original_stack_size: usize, reachable: bool, }, Loop { destination: Ebb, header: Ebb, - return_values: Vec, + num_return_values: usize, original_stack_size: usize, reachable: bool, }, @@ -44,11 +44,11 @@ pub enum ControlStackFrame { /// Helper methods for the control stack objects. impl ControlStackFrame { - pub fn return_values(&self) -> &[Type] { + pub fn num_return_values(&self) -> usize { match *self { - ControlStackFrame::If { ref return_values, .. } | - ControlStackFrame::Block { ref return_values, .. } | - ControlStackFrame::Loop { ref return_values, .. } => &return_values, + ControlStackFrame::If { num_return_values, .. } | + ControlStackFrame::Block { num_return_values, .. } | + ControlStackFrame::Loop { num_return_values, .. } => num_return_values, } } pub fn following_code(&self) -> Ebb { @@ -161,8 +161,7 @@ impl TranslationState { sig.return_types .iter() .filter(|arg| arg.purpose == ir::ArgumentPurpose::Normal) - .map(|argty| argty.value_type) - .collect(), + .count(), ); } @@ -215,33 +214,33 @@ impl TranslationState { } // Push a block on the control stack. - pub fn push_block(&mut self, following_code: Ebb, result_types: Vec) { + pub fn push_block(&mut self, following_code: Ebb, num_result_types: usize) { self.control_stack.push(ControlStackFrame::Block { destination: following_code, original_stack_size: self.stack.len(), - return_values: result_types, + num_return_values: num_result_types, reachable: false, }); } // Push a loop on the control stack. - pub fn push_loop(&mut self, header: Ebb, following_code: Ebb, result_types: Vec) { + pub fn push_loop(&mut self, header: Ebb, following_code: Ebb, num_result_types: usize) { self.control_stack.push(ControlStackFrame::Loop { header, destination: following_code, original_stack_size: self.stack.len(), - return_values: result_types, + num_return_values: num_result_types, reachable: false, }); } // Push an if on the control stack. - pub fn push_if(&mut self, branch_inst: Inst, following_code: Ebb, result_types: Vec) { + pub fn push_if(&mut self, branch_inst: Inst, following_code: Ebb, num_result_types: usize) { self.control_stack.push(ControlStackFrame::If { branch_inst, destination: following_code, original_stack_size: self.stack.len(), - return_values: result_types, + num_return_values: num_result_types, reachable: false, }); } diff --git a/lib/wasm/src/translation_utils.rs b/lib/wasm/src/translation_utils.rs index 2d522a1ba8..c21b580b29 100644 --- a/lib/wasm/src/translation_utils.rs +++ b/lib/wasm/src/translation_utils.rs @@ -119,13 +119,13 @@ pub fn f64_translation(x: wasmparser::Ieee64) -> cretonne::ir::immediates::Ieee6 } /// Translate a `wasmparser` type into its `Cretonne` equivalent, when possible -pub fn translate_type(ty: wasmparser::Type) -> Vec { +pub fn num_return_values(ty: wasmparser::Type) -> usize { match ty { - wasmparser::Type::EmptyBlockType => Vec::new(), - wasmparser::Type::I32 => vec![cretonne::ir::types::I32], - wasmparser::Type::F32 => vec![cretonne::ir::types::F32], - wasmparser::Type::I64 => vec![cretonne::ir::types::I64], - wasmparser::Type::F64 => vec![cretonne::ir::types::F64], + wasmparser::Type::EmptyBlockType => 0, + wasmparser::Type::I32 | + wasmparser::Type::F32 | + wasmparser::Type::I64 | + wasmparser::Type::F64 => 1, _ => panic!("unsupported return value type"), } }