diff --git a/lib/wasmstandalone/src/execution.rs b/lib/wasmstandalone/src/execution.rs index a8965fccaf..b159f79677 100644 --- a/lib/wasmstandalone/src/execution.rs +++ b/lib/wasmstandalone/src/execution.rs @@ -66,20 +66,20 @@ pub struct ExecutableCode { /// Executes a module that has been translated with the `StandaloneRuntime` runtime implementation. pub fn compile_module(trans_result: &TranslationResult) -> Result { let mut shared_builder = settings::builder(); - shared_builder - .enable("enable_verifier") - .expect("Missing enable_verifier setting"); - shared_builder - .set("is_64bit", "1") - .expect("Missing 64bits setting"); + shared_builder.enable("enable_verifier").expect( + "Missing enable_verifier setting", + ); + shared_builder.set("is_64bit", "1").expect( + "Missing 64bits setting", + ); let isa = match isa::lookup("intel") { Err(_) => { panic!() // The target ISA is not available. } Ok(mut isa_builder) => { - isa_builder - .enable("haswell") - .expect("Missing haswell setting"); + isa_builder.enable("haswell").expect( + "Missing haswell setting", + ); isa_builder.finish(settings::Flags::new(&shared_builder)) } }; @@ -90,7 +90,8 @@ pub fn compile_module(trans_result: &TranslationResult) -> Result { if trans_result.start_index.is_some() && - trans_result.start_index.unwrap() == function_index { + trans_result.start_index.unwrap() == function_index + { return Err(String::from("start function should not be an import")); } else { functions_code.push(Vec::new()); @@ -106,10 +107,9 @@ pub fn compile_module(trans_result: &TranslationResult) -> Result Result Err(String::from("No start function defined, aborting execution")), + None => Err(String::from( + "No start function defined, aborting execution", + )), Some(index) => { Ok(ExecutableCode { - functions_code, - start_index: index, - }) + functions_code, + start_index: index, + }) } } } @@ -141,13 +143,17 @@ pub fn compile_module(trans_result: &TranslationResult) -> Result Result<(), String> { let code_buf = &exec.functions_code[exec.start_index]; unsafe { - match protect(code_buf.as_ptr(), - code_buf.len(), - Protection::ReadWriteExecute) { + match protect( + code_buf.as_ptr(), + code_buf.len(), + Protection::ReadWriteExecute, + ) { Ok(()) => (), Err(err) => { - return Err(format!("failed to give executable permission to code: {}", - err.description())) + return Err(format!( + "failed to give executable permission to code: {}", + err.description() + )) } }; // Rather than writing inline assembly to jump to the code region, we use the fact that @@ -199,12 +205,12 @@ fn relocate(functions_metatada: &Vec, functions_code: &mut Vec for (_, &(func_ref, offset)) in relocs.funcs.iter() { let target_func_index = imports.functions[&func_ref]; let target_func_address: isize = functions_code[target_func_index].as_ptr() as - isize; + isize; unsafe { let reloc_address: isize = functions_code[func_index] .as_mut_ptr() .offset(offset as isize + 4) as - isize; + isize; let reloc_delta_i32: i32 = (target_func_address - reloc_address) as i32; write_unaligned(reloc_address as *mut i32, reloc_delta_i32); } @@ -214,12 +220,12 @@ fn relocate(functions_metatada: &Vec, functions_code: &mut Vec let reloc_address: isize = functions_code[func_index] .as_mut_ptr() .offset(offset as isize + 4) as - isize; - let target_ebb_address: isize = - functions_code[func_index] - .as_ptr() - .offset(il_func.offsets[ebb] as isize) as isize; + let target_ebb_address: isize = + functions_code[func_index].as_ptr().offset( + il_func.offsets[ebb] as + isize, + ) as isize; let reloc_delta_i32: i32 = (target_ebb_address - reloc_address) as i32; write_unaligned(reloc_address as *mut i32, reloc_delta_i32); } @@ -231,10 +237,11 @@ fn relocate(functions_metatada: &Vec, functions_code: &mut Vec } /// Pretty-print a verifier error. -pub fn pretty_verifier_error(func: &Function, - isa: Option<&TargetIsa>, - err: verifier::Error) - -> String { +pub fn pretty_verifier_error( + func: &Function, + isa: Option<&TargetIsa>, + err: verifier::Error, +) -> String { let mut msg = err.to_string(); match err.location { AnyEntity::Inst(inst) => { diff --git a/lib/wasmstandalone/src/standalone.rs b/lib/wasmstandalone/src/standalone.rs index 2a42075048..fa3ac08173 100644 --- a/lib/wasmstandalone/src/standalone.rs +++ b/lib/wasmstandalone/src/standalone.rs @@ -1,5 +1,5 @@ use cton_wasm::{Local, FunctionIndex, GlobalIndex, TableIndex, MemoryIndex, RawByte, - MemoryAddress, Global, GlobalInit, Table, Memory, WasmRuntime}; + MemoryAddress, Global, GlobalInit, Table, Memory, WasmRuntime}; use cton_frontend::FunctionBuilder; use cretonne::ir::{MemFlags, Value, InstBuilder, SigRef, FuncRef, ExtFuncData, FunctionName, Signature, ArgumentType, CallConv}; @@ -72,10 +72,11 @@ impl StandaloneRuntime { /// tells how to translate runtime-dependent wasm instructions. These functions should not be /// called by the user. impl WasmRuntime for StandaloneRuntime { - fn translate_get_global(&self, - builder: &mut FunctionBuilder, - global_index: GlobalIndex) - -> Value { + fn translate_get_global( + &self, + builder: &mut FunctionBuilder, + global_index: GlobalIndex, + ) -> Value { debug_assert!(self.instantiated); let ty = self.globals.info[global_index as usize].global.ty; let offset = self.globals.info[global_index as usize].offset; @@ -85,10 +86,12 @@ impl WasmRuntime for StandaloneRuntime { let addr_val = builder.ins().iconst(I64, addr); builder.ins().load(ty, memflags, addr_val, memoffset) } - fn translate_set_global(&self, - builder: &mut FunctionBuilder, - global_index: GlobalIndex, - val: Value) { + fn translate_set_global( + &self, + builder: &mut FunctionBuilder, + global_index: GlobalIndex, + val: Value, + ) { let offset = self.globals.info[global_index as usize].offset; let memflags = MemFlags::new(); let memoffset = Offset32::new(offset as i32); @@ -96,32 +99,33 @@ impl WasmRuntime for StandaloneRuntime { let addr_val = builder.ins().iconst(I64, addr); builder.ins().store(memflags, val, addr_val, memoffset); } - fn translate_memory_base_address(&self, - builder: &mut FunctionBuilder, - memory_index: MemoryIndex) - -> Value { + fn translate_memory_base_address( + &self, + builder: &mut FunctionBuilder, + memory_index: MemoryIndex, + ) -> Value { let addr: i64 = unsafe { transmute(self.memories[memory_index].data.as_ptr()) }; builder.ins().iconst(I64, addr) } - fn translate_grow_memory(&mut self, - builder: &mut FunctionBuilder, - pages: Value) - -> Value { + fn translate_grow_memory( + &mut self, + builder: &mut FunctionBuilder, + pages: Value, + ) -> Value { debug_assert!(self.instantiated); let grow_mem_func = match self.has_grow_memory { Some(grow_mem_func) => grow_mem_func, None => { - let sig_ref = - builder.import_signature(Signature { - call_conv: CallConv::Native, - argument_bytes: None, - argument_types: vec![ArgumentType::new(I32)], - return_types: vec![ArgumentType::new(I32)], - }); + let sig_ref = builder.import_signature(Signature { + call_conv: CallConv::Native, + argument_bytes: None, + argument_types: vec![ArgumentType::new(I32)], + return_types: vec![ArgumentType::new(I32)], + }); builder.import_function(ExtFuncData { - name: FunctionName::new("grow_memory"), - signature: sig_ref, - }) + name: FunctionName::new("grow_memory"), + signature: sig_ref, + }) } }; self.has_grow_memory = Some(grow_mem_func); @@ -134,42 +138,46 @@ impl WasmRuntime for StandaloneRuntime { Some(cur_mem_func) => cur_mem_func, None => { let sig_ref = builder.import_signature(Signature { - call_conv: CallConv::Native, - argument_bytes: None, - argument_types: Vec::new(), - return_types: - vec![ArgumentType::new(I32)], - }); + call_conv: CallConv::Native, + argument_bytes: None, + argument_types: Vec::new(), + return_types: vec![ArgumentType::new(I32)], + }); builder.import_function(ExtFuncData { - name: FunctionName::new("current_memory"), - signature: sig_ref, - }) + name: FunctionName::new("current_memory"), + signature: sig_ref, + }) } }; self.has_current_memory = Some(cur_mem_func); let call_inst = builder.ins().call(cur_mem_func, &[]); *builder.inst_results(call_inst).first().unwrap() } - fn translate_call_indirect<'a>(&self, - builder: &'a mut FunctionBuilder, - sig_ref: SigRef, - index_val: Value, - call_args: &[Value]) - -> &'a [Value] { + fn translate_call_indirect<'a>( + &self, + builder: &'a mut FunctionBuilder, + sig_ref: SigRef, + index_val: Value, + call_args: &[Value], + ) -> &'a [Value] { let trap_ebb = builder.create_ebb(); let continue_ebb = builder.create_ebb(); let size_val = builder.ins().iconst(I32, self.tables[0].info.size as i64); let zero_val = builder.ins().iconst(I32, 0); - builder - .ins() - .br_icmp(IntCC::UnsignedLessThan, index_val, zero_val, trap_ebb, &[]); - builder - .ins() - .br_icmp(IntCC::UnsignedGreaterThanOrEqual, - index_val, - size_val, - trap_ebb, - &[]); + builder.ins().br_icmp( + IntCC::UnsignedLessThan, + index_val, + zero_val, + trap_ebb, + &[], + ); + builder.ins().br_icmp( + IntCC::UnsignedGreaterThanOrEqual, + index_val, + size_val, + trap_ebb, + &[], + ); builder.seal_block(trap_ebb); let offset_val = builder.ins().imul_imm(index_val, 4); let base_table_addr: i64 = unsafe { transmute(self.tables[0].data.as_ptr()) }; @@ -177,12 +185,17 @@ impl WasmRuntime for StandaloneRuntime { let table_entry_addr_val = builder.ins().iadd(table_addr_val, offset_val); let memflags = MemFlags::new(); let memoffset = Offset32::new(0); - let table_entry_val = builder - .ins() - .load(I32, memflags, table_entry_addr_val, memoffset); - let call_inst = builder - .ins() - .call_indirect(sig_ref, table_entry_val, call_args); + let table_entry_val = builder.ins().load( + I32, + memflags, + table_entry_addr_val, + memoffset, + ); + let call_inst = builder.ins().call_indirect( + sig_ref, + table_entry_val, + call_args, + ); builder.ins().jump(continue_ebb, &[]); builder.seal_block(continue_ebb); builder.switch_to_block(trap_ebb, &[]); @@ -205,36 +218,36 @@ impl WasmRuntime for StandaloneRuntime { for globalinfo in self.globals.info.iter() { match globalinfo.global.initializer { GlobalInit::I32Const(val) => unsafe { - write(self.globals - .data - .as_mut_ptr() - .offset(globalinfo.offset as isize) as - *mut i32, - val) + write( + self.globals.data.as_mut_ptr().offset( + globalinfo.offset as isize, + ) as *mut i32, + val, + ) }, GlobalInit::I64Const(val) => unsafe { - write(self.globals - .data - .as_mut_ptr() - .offset(globalinfo.offset as isize) as - *mut i64, - val) + write( + self.globals.data.as_mut_ptr().offset( + globalinfo.offset as isize, + ) as *mut i64, + val, + ) }, GlobalInit::F32Const(val) => unsafe { - write(self.globals - .data - .as_mut_ptr() - .offset(globalinfo.offset as isize) as - *mut f32, - transmute(val)) + write( + self.globals.data.as_mut_ptr().offset( + globalinfo.offset as isize, + ) as *mut f32, + transmute(val), + ) }, GlobalInit::F64Const(val) => unsafe { - write(self.globals - .data - .as_mut_ptr() - .offset(globalinfo.offset as isize) as - *mut f64, - transmute(val)) + write( + self.globals.data.as_mut_ptr().offset( + globalinfo.offset as isize, + ) as *mut f64, + transmute(val), + ) }, GlobalInit::Import() => { // We don't initialize, this is inter-module linking @@ -244,10 +257,9 @@ impl WasmRuntime for StandaloneRuntime { let ref_offset = self.globals.info[index].offset; let size = globalinfo.global.ty.bytes(); unsafe { - let dst = self.globals - .data - .as_mut_ptr() - .offset(globalinfo.offset as isize); + let dst = self.globals.data.as_mut_ptr().offset( + globalinfo.offset as isize, + ); let src = self.globals.data.as_ptr().offset(ref_offset as isize); copy_nonoverlapping(src, dst, size as usize) } @@ -261,12 +273,10 @@ impl WasmRuntime for StandaloneRuntime { } fn declare_global(&mut self, global: Global) { debug_assert!(!self.instantiated); - self.globals - .info - .push(GlobalInfo { - global: global, - offset: 0, - }); + self.globals.info.push(GlobalInfo { + global: global, + offset: 0, + }); } fn declare_table(&mut self, table: Table) { debug_assert!(!self.instantiated); @@ -274,17 +284,18 @@ impl WasmRuntime for StandaloneRuntime { elements_vec.resize(table.size as usize, TableElement::Trap()); let mut addresses_vec = Vec::with_capacity(table.size as usize); addresses_vec.resize(table.size as usize, 0); - self.tables - .push(TableData { - info: table, - data: addresses_vec, - elements: elements_vec, - }); + self.tables.push(TableData { + info: table, + data: addresses_vec, + elements: elements_vec, + }); } - fn declare_table_elements(&mut self, - table_index: TableIndex, - offset: usize, - elements: &[FunctionIndex]) { + fn declare_table_elements( + &mut self, + table_index: TableIndex, + offset: usize, + elements: &[FunctionIndex], + ) { debug_assert!(!self.instantiated); for (i, elt) in elements.iter().enumerate() { self.tables[table_index].elements[offset as usize + i] = TableElement::Function(*elt); @@ -294,17 +305,17 @@ impl WasmRuntime for StandaloneRuntime { debug_assert!(!self.instantiated); let mut memory_vec = Vec::with_capacity(memory.pages_count as usize * PAGE_SIZE); memory_vec.resize(memory.pages_count as usize * PAGE_SIZE, 0); - self.memories - .push(MemoryData { - info: memory, - data: memory_vec, - }); + self.memories.push(MemoryData { + info: memory, + data: memory_vec, + }); } - fn declare_data_initialization(&mut self, - memory_index: MemoryIndex, - offset: usize, - data: &[u8]) - -> Result<(), String> { + fn declare_data_initialization( + &mut self, + memory_index: MemoryIndex, + offset: usize, + data: &[u8], + ) -> Result<(), String> { if offset + data.len() > self.memories[memory_index].info.pages_count * PAGE_SIZE { return Err(String::from("initialization data out of bounds")); } @@ -318,15 +329,17 @@ impl StandaloneRuntime { /// Returns a slice of the contents of allocated linear memory. pub fn inspect_memory(&self, memory_index: usize, address: usize, len: usize) -> &[u8] { &self.memories - .get(memory_index) - .expect(format!("no memory for index {}", memory_index).as_str()) - .data - [address..address + len] + .get(memory_index) + .expect(format!("no memory for index {}", memory_index).as_str()) + .data + [address..address + len] } /// Shows the value of a global variable. pub fn inspect_global(&self, global_index: usize) -> &[u8] { - let (offset, len) = (self.globals.info[global_index].offset, - self.globals.info[global_index].global.ty.bytes() as usize); + let (offset, len) = ( + self.globals.info[global_index].offset, + self.globals.info[global_index].global.ty.bytes() as usize, + ); &self.globals.data[offset..offset + len] } } diff --git a/src/main.rs b/src/main.rs index 21b9bca71f..411d18b594 100644 --- a/src/main.rs +++ b/src/main.rs @@ -101,7 +101,9 @@ fn read_wasm_file(path: PathBuf) -> Result, io::Error> { fn main() { let args: Args = Docopt::new(USAGE) - .and_then(|d| d.help(true).version(Some(format!("0.0.0"))).deserialize()) + .and_then(|d| { + d.help(true).version(Some(format!("0.0.0"))).deserialize() + }) .unwrap_or_else(|e| e.exit()); let mut terminal = term::stdout().unwrap(); for filename in args.arg_file.iter() { @@ -152,10 +154,10 @@ fn handle_module(args: &Args, path: PathBuf, name: String) -> Result<(), String> .arg(file_path.to_str().unwrap()) .output() .or_else(|e| if let io::ErrorKind::NotFound = e.kind() { - return Err(String::from("wast2wasm not found")); - } else { - return Err(String::from(e.description())); - }) + return Err(String::from("wast2wasm not found")); + } else { + return Err(String::from(e.description())); + }) .unwrap(); match read_wasm_file(file_path) { Ok(data) => data, @@ -312,16 +314,15 @@ fn handle_module(args: &Args, path: PathBuf, name: String) -> Result<(), String> if split.len() != 3 { break; } - let memory = standalone_runtime - .inspect_memory(str::parse(split[0]).unwrap(), - str::parse(split[1]).unwrap(), - str::parse(split[2]).unwrap()); - let mut s = memory - .iter() - .fold(String::from("#"), |mut acc, byte| { - acc.push_str(format!("{:02x}_", byte).as_str()); - acc - }); + let memory = standalone_runtime.inspect_memory( + str::parse(split[0]).unwrap(), + str::parse(split[1]).unwrap(), + str::parse(split[2]).unwrap(), + ); + let mut s = memory.iter().fold(String::from("#"), |mut acc, byte| { + acc.push_str(format!("{:02x}_", byte).as_str()); + acc + }); s.pop(); println!("{}", s); } @@ -334,22 +335,20 @@ fn handle_module(args: &Args, path: PathBuf, name: String) -> Result<(), String> } // Prints out a Wasm module, and for each function the corresponding translation in Cretonne IL. -fn pretty_print_translation(filename: &String, - data: &Vec, - translation: &TranslationResult, - writer_wast: &mut Write, - writer_cretonne: &mut Write) - -> Result<(), io::Error> { +fn pretty_print_translation( + filename: &String, + data: &Vec, + translation: &TranslationResult, + writer_wast: &mut Write, + writer_cretonne: &mut Write, +) -> Result<(), io::Error> { let mut terminal = term::stdout().unwrap(); let mut parser = Parser::new(data.as_slice()); let mut parser_writer = Writer::new(writer_wast); - let imports_count = translation - .functions - .iter() - .fold(0, |acc, &ref f| match f { - &FunctionTranslation::Import() => acc + 1, - &FunctionTranslation::Code { .. } => acc, - }); + let imports_count = translation.functions.iter().fold(0, |acc, &ref f| match f { + &FunctionTranslation::Import() => acc + 1, + &FunctionTranslation::Code { .. } => acc, + }); match parser.read() { s @ &ParserState::BeginWasm { .. } => parser_writer.write(&s)?, _ => panic!("modules should begin properly"), @@ -370,10 +369,12 @@ fn pretty_print_translation(filename: &String, match parser.read() { s @ &ParserState::BeginFunctionBody { .. } => { terminal.fg(term::color::BLUE).unwrap(); - write!(writer_cretonne, - "====== Function No. {} of module \"{}\" ======\n", - function_index, - filename)?; + write!( + writer_cretonne, + "====== Function No. {} of module \"{}\" ======\n", + function_index, + filename + )?; terminal.fg(term::color::CYAN).unwrap(); write!(writer_cretonne, "Wast ---------->\n")?; terminal.reset().unwrap(); @@ -398,13 +399,13 @@ fn pretty_print_translation(filename: &String, }; } } - let mut function_string = - format!(" {}", - match translation.functions[function_index + imports_count] { - FunctionTranslation::Code { ref il, .. } => il, - FunctionTranslation::Import() => panic!("should not happen"), - } - .display(None)); + let mut function_string = format!( + " {}", + match translation.functions[function_index + imports_count] { + FunctionTranslation::Code { ref il, .. } => il, + FunctionTranslation::Import() => panic!("should not happen"), + }.display(None) + ); function_string.pop(); let function_str = str::replace(function_string.as_str(), "\n", "\n "); terminal.fg(term::color::CYAN).unwrap(); @@ -422,17 +423,20 @@ fn pretty_print_translation(filename: &String, } /// Pretty-print a verifier error. -pub fn pretty_verifier_error(func: &ir::Function, - isa: Option<&TargetIsa>, - err: verifier::Error) - -> String { +pub fn pretty_verifier_error( + func: &ir::Function, + isa: Option<&TargetIsa>, + err: verifier::Error, +) -> String { let msg = err.to_string(); let str1 = match err.location { AnyEntity::Inst(inst) => { - format!("{}\n{}: {}\n\n", - msg, - inst, - func.dfg.display_inst(inst, isa)) + format!( + "{}\n{}: {}\n\n", + msg, + inst, + func.dfg.display_inst(inst, isa) + ) } _ => String::from(format!("{}\n", msg)), };