diff --git a/lib/filecheck/src/checker.rs b/lib/filecheck/src/checker.rs index 9c88df8eb4..d48c0ba3e4 100644 --- a/lib/filecheck/src/checker.rs +++ b/lib/filecheck/src/checker.rs @@ -6,6 +6,7 @@ use std::borrow::Cow; use std::collections::HashMap; use std::cmp::max; use std::fmt::{self, Display, Formatter}; +use std::mem; use MatchRange; use explain::{Recorder, Explainer}; @@ -131,7 +132,9 @@ impl CheckerBuilder { pub fn finish(&mut self) -> Checker { // Move directives into the new checker, leaving `self.directives` empty and ready for // building a new checker. - Checker::new(self.directives.split_off(0)) + let mut new_directives = Vec::new(); + mem::swap(&mut new_directives, &mut self.directives); + Checker::new(new_directives) } } diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index 83b123e8f6..b057aa11c8 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -153,8 +153,8 @@ pub fn translate_function_body( // explicitely in Cretonne IL. if !builder.is_filled() && (!builder.is_unreachable() || !builder.is_pristine()) { let cut_index = state.stack.len() - sig.return_types.len(); - let return_vals = state.stack.split_off(cut_index); - builder.ins().return_(&return_vals); + 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(); @@ -167,8 +167,8 @@ pub fn translate_function_body( builder.ebb_args(frame.following_code()), ); let cut_index = state.stack.len() - sig.return_types.len(); - let return_vals = state.stack.split_off(cut_index); - builder.ins().return_(&return_vals); + builder.ins().return_(&state.stack[cut_index..]); + state.stack.truncate(cut_index); } } Ok((func, func_imports)) @@ -288,8 +288,8 @@ fn translate_operator( _ => panic!("should not happen"), }; let cut_index = state.stack.len() - return_values.len(); - let jump_args = state.stack.split_off(cut_index); - builder.ins().jump(destination, &jump_args); + builder.ins().jump(destination, &state.stack[cut_index..]); + state.stack.truncate(cut_index); // We change the target of the branch instruction let else_ebb = builder.create_ebb(); builder.change_jump_destination(branch_inst, else_ebb); @@ -300,8 +300,11 @@ fn translate_operator( let frame = state.control_stack.pop().unwrap(); if !builder.is_unreachable() || !builder.is_pristine() { let cut_index = state.stack.len() - frame.return_values().len(); - let jump_args = state.stack.split_off(cut_index); - builder.ins().jump(frame.following_code(), &jump_args); + builder.ins().jump( + frame.following_code(), + &state.stack[cut_index..], + ); + state.stack.truncate(cut_index); } builder.switch_to_block(frame.following_code(), frame.return_values()); builder.seal_block(frame.following_code()); @@ -339,13 +342,17 @@ fn translate_operator( Operator::Br { relative_depth } => { let i = state.control_stack.len() - 1 - (relative_depth as usize); let frame = &mut state.control_stack[i]; - let jump_args = if frame.is_loop() { - Vec::new() - } else { - let cut_index = state.stack.len() - frame.return_values().len(); - state.stack.split_off(cut_index) - }; - builder.ins().jump(frame.br_destination(), &jump_args); + let cut_index = state.stack.len() - + if frame.is_loop() { + 0 + } else { + frame.return_values().len() + }; + builder.ins().jump( + frame.br_destination(), + &state.stack[cut_index..], + ); + state.stack.truncate(cut_index); // We signal that all the code that follows until the next End is unreachable frame.set_reachable(); state.real_unreachable_stack_depth = 1 + relative_depth as usize; @@ -354,17 +361,20 @@ fn translate_operator( let val = state.pop1(); let i = state.control_stack.len() - 1 - (relative_depth as usize); let frame = &mut state.control_stack[i]; - let jump_args = if frame.is_loop() { - Vec::new() - } else { - let cut_index = state.stack.len() - frame.return_values().len(); - state.stack.split_off(cut_index) - }; - builder.ins().brnz(val, frame.br_destination(), &jump_args); + let cut_index = state.stack.len() - + if frame.is_loop() { + 0 + } else { + frame.return_values().len() + }; + builder.ins().brnz( + val, + frame.br_destination(), + &state.stack[cut_index..], + ); // The values returned by the branch are still available for the reachable // code that comes after it frame.set_reachable(); - state.stack.extend(jump_args); } Operator::BrTable { ref table } => { let (depths, default) = table.read_table(); @@ -406,7 +416,6 @@ fn translate_operator( // We then proceed to split the edges going out of the br_table let val = state.pop1(); let cut_index = state.stack.len() - jump_args_count; - let jump_args = state.stack.split_off(cut_index); let jt = builder.create_jump_table(); let dest_ebbs: HashMap = depths.iter().enumerate().fold(HashMap::new(), |mut acc, @@ -425,25 +434,25 @@ fn translate_operator( let default_ebb = state.control_stack[state.control_stack.len() - 1 - (default as usize)] .br_destination(); - builder.ins().jump(default_ebb, &jump_args); - state.stack.extend_from_slice(&jump_args); + builder.ins().jump(default_ebb, &state.stack[cut_index..]); for (depth, dest_ebb) in dest_ebbs { builder.switch_to_block(dest_ebb, &[]); builder.seal_block(dest_ebb); let i = state.control_stack.len() - 1 - depth; let frame = &mut state.control_stack[i]; let real_dest_ebb = frame.br_destination(); - builder.ins().jump(real_dest_ebb, &jump_args); + builder.ins().jump(real_dest_ebb, &state.stack[cut_index..]); frame.set_reachable(); } + state.stack.truncate(cut_index); state.real_unreachable_stack_depth = 1 + min_depth as usize; } } Operator::Return => { let return_count = sig.return_types.len(); let cut_index = state.stack.len() - return_count; - let return_args = state.stack.split_off(cut_index); - builder.ins().return_(&return_args); + builder.ins().return_(&state.stack[cut_index..]); + state.stack.truncate(cut_index); state.real_unreachable_stack_depth = 1; } /************************************ Calls **************************************** @@ -454,7 +463,6 @@ fn translate_operator( Operator::Call { function_index } => { let args_num = args_count(function_index as usize, functions, signatures); let cut_index = state.stack.len() - args_num; - let call_args = state.stack.split_off(cut_index); let internal_function_index = find_function_import( function_index as usize, builder, @@ -463,7 +471,11 @@ fn translate_operator( exports, signatures, ); - let call_inst = builder.ins().call(internal_function_index, &call_args); + let call_inst = builder.ins().call( + internal_function_index, + &state.stack[cut_index..], + ); + state.stack.truncate(cut_index); let ret_values = builder.inst_results(call_inst); for val in ret_values { state.push1(*val); @@ -480,9 +492,13 @@ fn translate_operator( let args_num = builder.signature(sigref).unwrap().argument_types.len(); let index_val = state.pop1(); let cut_index = state.stack.len() - args_num; - let call_args = state.stack.split_off(cut_index); - let ret_values = - runtime.translate_call_indirect(builder, sigref, index_val, &call_args); + let ret_values = runtime.translate_call_indirect( + builder, + sigref, + index_val, + &state.stack[cut_index..], + ); + state.stack.truncate(cut_index); for val in ret_values { state.push1(*val); }