Format with rustfmt 0.9.0.

This commit is contained in:
Dan Gohman
2017-09-06 08:37:12 -07:00
parent d0fe50a2a8
commit 3868467917
3 changed files with 227 additions and 203 deletions

View File

@@ -66,20 +66,20 @@ pub struct ExecutableCode {
/// Executes a module that has been translated with the `StandaloneRuntime` runtime implementation. /// Executes a module that has been translated with the `StandaloneRuntime` runtime implementation.
pub fn compile_module(trans_result: &TranslationResult) -> Result<ExecutableCode, String> { pub fn compile_module(trans_result: &TranslationResult) -> Result<ExecutableCode, String> {
let mut shared_builder = settings::builder(); let mut shared_builder = settings::builder();
shared_builder shared_builder.enable("enable_verifier").expect(
.enable("enable_verifier") "Missing enable_verifier setting",
.expect("Missing enable_verifier setting"); );
shared_builder shared_builder.set("is_64bit", "1").expect(
.set("is_64bit", "1") "Missing 64bits setting",
.expect("Missing 64bits setting"); );
let isa = match isa::lookup("intel") { let isa = match isa::lookup("intel") {
Err(_) => { Err(_) => {
panic!() // The target ISA is not available. panic!() // The target ISA is not available.
} }
Ok(mut isa_builder) => { Ok(mut isa_builder) => {
isa_builder isa_builder.enable("haswell").expect(
.enable("haswell") "Missing haswell setting",
.expect("Missing haswell setting"); );
isa_builder.finish(settings::Flags::new(&shared_builder)) isa_builder.finish(settings::Flags::new(&shared_builder))
} }
}; };
@@ -90,7 +90,8 @@ pub fn compile_module(trans_result: &TranslationResult) -> Result<ExecutableCode
let (il, imports) = match function { let (il, imports) = match function {
&FunctionTranslation::Import() => { &FunctionTranslation::Import() => {
if trans_result.start_index.is_some() && 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")); return Err(String::from("start function should not be an import"));
} else { } else {
functions_code.push(Vec::new()); functions_code.push(Vec::new());
@@ -106,10 +107,9 @@ pub fn compile_module(trans_result: &TranslationResult) -> Result<ExecutableCode
}; };
verify_function(&il, None).unwrap(); verify_function(&il, None).unwrap();
context.func = il; context.func = il;
let code_size = context let code_size = context.compile(&*isa).map_err(|e| {
.compile(&*isa) pretty_error(&context.func, Some(&*isa), e)
.map_err(|e| pretty_error(&context.func, Some(&*isa), e))? as })? as usize;
usize;
if code_size == 0 { if code_size == 0 {
return Err(String::from("no code generated by Cretonne")); return Err(String::from("no code generated by Cretonne"));
} }
@@ -118,21 +118,23 @@ pub fn compile_module(trans_result: &TranslationResult) -> Result<ExecutableCode
let mut relocsink = StandaloneRelocSink::new(); let mut relocsink = StandaloneRelocSink::new();
context.emit_to_memory(code_buf.as_mut_ptr(), &mut relocsink, &*isa); context.emit_to_memory(code_buf.as_mut_ptr(), &mut relocsink, &*isa);
functions_metatada.push(FunctionMetaData::Local { functions_metatada.push(FunctionMetaData::Local {
relocs: relocsink, relocs: relocsink,
imports: imports, imports: imports,
il_func: context.func, il_func: context.func,
}); });
functions_code.push(code_buf); functions_code.push(code_buf);
} }
relocate(&functions_metatada, &mut functions_code); relocate(&functions_metatada, &mut functions_code);
// After having emmitted the code to memory, we deal with relocations // After having emmitted the code to memory, we deal with relocations
match trans_result.start_index { match trans_result.start_index {
None => Err(String::from("No start function defined, aborting execution")), None => Err(String::from(
"No start function defined, aborting execution",
)),
Some(index) => { Some(index) => {
Ok(ExecutableCode { Ok(ExecutableCode {
functions_code, functions_code,
start_index: index, start_index: index,
}) })
} }
} }
} }
@@ -141,13 +143,17 @@ pub fn compile_module(trans_result: &TranslationResult) -> Result<ExecutableCode
pub fn execute(exec: ExecutableCode) -> Result<(), String> { pub fn execute(exec: ExecutableCode) -> Result<(), String> {
let code_buf = &exec.functions_code[exec.start_index]; let code_buf = &exec.functions_code[exec.start_index];
unsafe { unsafe {
match protect(code_buf.as_ptr(), match protect(
code_buf.len(), code_buf.as_ptr(),
Protection::ReadWriteExecute) { code_buf.len(),
Protection::ReadWriteExecute,
) {
Ok(()) => (), Ok(()) => (),
Err(err) => { Err(err) => {
return Err(format!("failed to give executable permission to code: {}", return Err(format!(
err.description())) "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 // 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<FunctionMetaData>, functions_code: &mut Vec
for (_, &(func_ref, offset)) in relocs.funcs.iter() { for (_, &(func_ref, offset)) in relocs.funcs.iter() {
let target_func_index = imports.functions[&func_ref]; let target_func_index = imports.functions[&func_ref];
let target_func_address: isize = functions_code[target_func_index].as_ptr() as let target_func_address: isize = functions_code[target_func_index].as_ptr() as
isize; isize;
unsafe { unsafe {
let reloc_address: isize = functions_code[func_index] let reloc_address: isize = functions_code[func_index]
.as_mut_ptr() .as_mut_ptr()
.offset(offset as isize + 4) as .offset(offset as isize + 4) as
isize; isize;
let reloc_delta_i32: i32 = (target_func_address - reloc_address) as i32; let reloc_delta_i32: i32 = (target_func_address - reloc_address) as i32;
write_unaligned(reloc_address as *mut i32, reloc_delta_i32); write_unaligned(reloc_address as *mut i32, reloc_delta_i32);
} }
@@ -214,12 +220,12 @@ fn relocate(functions_metatada: &Vec<FunctionMetaData>, functions_code: &mut Vec
let reloc_address: isize = functions_code[func_index] let reloc_address: isize = functions_code[func_index]
.as_mut_ptr() .as_mut_ptr()
.offset(offset as isize + 4) as .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; 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; let reloc_delta_i32: i32 = (target_ebb_address - reloc_address) as i32;
write_unaligned(reloc_address as *mut i32, reloc_delta_i32); write_unaligned(reloc_address as *mut i32, reloc_delta_i32);
} }
@@ -231,10 +237,11 @@ fn relocate(functions_metatada: &Vec<FunctionMetaData>, functions_code: &mut Vec
} }
/// Pretty-print a verifier error. /// Pretty-print a verifier error.
pub fn pretty_verifier_error(func: &Function, pub fn pretty_verifier_error(
isa: Option<&TargetIsa>, func: &Function,
err: verifier::Error) isa: Option<&TargetIsa>,
-> String { err: verifier::Error,
) -> String {
let mut msg = err.to_string(); let mut msg = err.to_string();
match err.location { match err.location {
AnyEntity::Inst(inst) => { AnyEntity::Inst(inst) => {

View File

@@ -1,5 +1,5 @@
use cton_wasm::{Local, FunctionIndex, GlobalIndex, TableIndex, MemoryIndex, RawByte, 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 cton_frontend::FunctionBuilder;
use cretonne::ir::{MemFlags, Value, InstBuilder, SigRef, FuncRef, ExtFuncData, FunctionName, use cretonne::ir::{MemFlags, Value, InstBuilder, SigRef, FuncRef, ExtFuncData, FunctionName,
Signature, ArgumentType, CallConv}; Signature, ArgumentType, CallConv};
@@ -72,10 +72,11 @@ impl StandaloneRuntime {
/// tells how to translate runtime-dependent wasm instructions. These functions should not be /// tells how to translate runtime-dependent wasm instructions. These functions should not be
/// called by the user. /// called by the user.
impl WasmRuntime for StandaloneRuntime { impl WasmRuntime for StandaloneRuntime {
fn translate_get_global(&self, fn translate_get_global(
builder: &mut FunctionBuilder<Local>, &self,
global_index: GlobalIndex) builder: &mut FunctionBuilder<Local>,
-> Value { global_index: GlobalIndex,
) -> Value {
debug_assert!(self.instantiated); debug_assert!(self.instantiated);
let ty = self.globals.info[global_index as usize].global.ty; let ty = self.globals.info[global_index as usize].global.ty;
let offset = self.globals.info[global_index as usize].offset; 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); let addr_val = builder.ins().iconst(I64, addr);
builder.ins().load(ty, memflags, addr_val, memoffset) builder.ins().load(ty, memflags, addr_val, memoffset)
} }
fn translate_set_global(&self, fn translate_set_global(
builder: &mut FunctionBuilder<Local>, &self,
global_index: GlobalIndex, builder: &mut FunctionBuilder<Local>,
val: Value) { global_index: GlobalIndex,
val: Value,
) {
let offset = self.globals.info[global_index as usize].offset; let offset = self.globals.info[global_index as usize].offset;
let memflags = MemFlags::new(); let memflags = MemFlags::new();
let memoffset = Offset32::new(offset as i32); let memoffset = Offset32::new(offset as i32);
@@ -96,32 +99,33 @@ impl WasmRuntime for StandaloneRuntime {
let addr_val = builder.ins().iconst(I64, addr); let addr_val = builder.ins().iconst(I64, addr);
builder.ins().store(memflags, val, addr_val, memoffset); builder.ins().store(memflags, val, addr_val, memoffset);
} }
fn translate_memory_base_address(&self, fn translate_memory_base_address(
builder: &mut FunctionBuilder<Local>, &self,
memory_index: MemoryIndex) builder: &mut FunctionBuilder<Local>,
-> Value { memory_index: MemoryIndex,
) -> Value {
let addr: i64 = unsafe { transmute(self.memories[memory_index].data.as_ptr()) }; let addr: i64 = unsafe { transmute(self.memories[memory_index].data.as_ptr()) };
builder.ins().iconst(I64, addr) builder.ins().iconst(I64, addr)
} }
fn translate_grow_memory(&mut self, fn translate_grow_memory(
builder: &mut FunctionBuilder<Local>, &mut self,
pages: Value) builder: &mut FunctionBuilder<Local>,
-> Value { pages: Value,
) -> Value {
debug_assert!(self.instantiated); debug_assert!(self.instantiated);
let grow_mem_func = match self.has_grow_memory { let grow_mem_func = match self.has_grow_memory {
Some(grow_mem_func) => grow_mem_func, Some(grow_mem_func) => grow_mem_func,
None => { None => {
let sig_ref = let sig_ref = builder.import_signature(Signature {
builder.import_signature(Signature { call_conv: CallConv::Native,
call_conv: CallConv::Native, argument_bytes: None,
argument_bytes: None, argument_types: vec![ArgumentType::new(I32)],
argument_types: vec![ArgumentType::new(I32)], return_types: vec![ArgumentType::new(I32)],
return_types: vec![ArgumentType::new(I32)], });
});
builder.import_function(ExtFuncData { builder.import_function(ExtFuncData {
name: FunctionName::new("grow_memory"), name: FunctionName::new("grow_memory"),
signature: sig_ref, signature: sig_ref,
}) })
} }
}; };
self.has_grow_memory = Some(grow_mem_func); self.has_grow_memory = Some(grow_mem_func);
@@ -134,42 +138,46 @@ impl WasmRuntime for StandaloneRuntime {
Some(cur_mem_func) => cur_mem_func, Some(cur_mem_func) => cur_mem_func,
None => { None => {
let sig_ref = builder.import_signature(Signature { let sig_ref = builder.import_signature(Signature {
call_conv: CallConv::Native, call_conv: CallConv::Native,
argument_bytes: None, argument_bytes: None,
argument_types: Vec::new(), argument_types: Vec::new(),
return_types: return_types: vec![ArgumentType::new(I32)],
vec![ArgumentType::new(I32)], });
});
builder.import_function(ExtFuncData { builder.import_function(ExtFuncData {
name: FunctionName::new("current_memory"), name: FunctionName::new("current_memory"),
signature: sig_ref, signature: sig_ref,
}) })
} }
}; };
self.has_current_memory = Some(cur_mem_func); self.has_current_memory = Some(cur_mem_func);
let call_inst = builder.ins().call(cur_mem_func, &[]); let call_inst = builder.ins().call(cur_mem_func, &[]);
*builder.inst_results(call_inst).first().unwrap() *builder.inst_results(call_inst).first().unwrap()
} }
fn translate_call_indirect<'a>(&self, fn translate_call_indirect<'a>(
builder: &'a mut FunctionBuilder<Local>, &self,
sig_ref: SigRef, builder: &'a mut FunctionBuilder<Local>,
index_val: Value, sig_ref: SigRef,
call_args: &[Value]) index_val: Value,
-> &'a [Value] { call_args: &[Value],
) -> &'a [Value] {
let trap_ebb = builder.create_ebb(); let trap_ebb = builder.create_ebb();
let continue_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 size_val = builder.ins().iconst(I32, self.tables[0].info.size as i64);
let zero_val = builder.ins().iconst(I32, 0); let zero_val = builder.ins().iconst(I32, 0);
builder builder.ins().br_icmp(
.ins() IntCC::UnsignedLessThan,
.br_icmp(IntCC::UnsignedLessThan, index_val, zero_val, trap_ebb, &[]); index_val,
builder zero_val,
.ins() trap_ebb,
.br_icmp(IntCC::UnsignedGreaterThanOrEqual, &[],
index_val, );
size_val, builder.ins().br_icmp(
trap_ebb, IntCC::UnsignedGreaterThanOrEqual,
&[]); index_val,
size_val,
trap_ebb,
&[],
);
builder.seal_block(trap_ebb); builder.seal_block(trap_ebb);
let offset_val = builder.ins().imul_imm(index_val, 4); let offset_val = builder.ins().imul_imm(index_val, 4);
let base_table_addr: i64 = unsafe { transmute(self.tables[0].data.as_ptr()) }; 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 table_entry_addr_val = builder.ins().iadd(table_addr_val, offset_val);
let memflags = MemFlags::new(); let memflags = MemFlags::new();
let memoffset = Offset32::new(0); let memoffset = Offset32::new(0);
let table_entry_val = builder let table_entry_val = builder.ins().load(
.ins() I32,
.load(I32, memflags, table_entry_addr_val, memoffset); memflags,
let call_inst = builder table_entry_addr_val,
.ins() memoffset,
.call_indirect(sig_ref, table_entry_val, call_args); );
let call_inst = builder.ins().call_indirect(
sig_ref,
table_entry_val,
call_args,
);
builder.ins().jump(continue_ebb, &[]); builder.ins().jump(continue_ebb, &[]);
builder.seal_block(continue_ebb); builder.seal_block(continue_ebb);
builder.switch_to_block(trap_ebb, &[]); builder.switch_to_block(trap_ebb, &[]);
@@ -205,36 +218,36 @@ impl WasmRuntime for StandaloneRuntime {
for globalinfo in self.globals.info.iter() { for globalinfo in self.globals.info.iter() {
match globalinfo.global.initializer { match globalinfo.global.initializer {
GlobalInit::I32Const(val) => unsafe { GlobalInit::I32Const(val) => unsafe {
write(self.globals write(
.data self.globals.data.as_mut_ptr().offset(
.as_mut_ptr() globalinfo.offset as isize,
.offset(globalinfo.offset as isize) as ) as *mut i32,
*mut i32, val,
val) )
}, },
GlobalInit::I64Const(val) => unsafe { GlobalInit::I64Const(val) => unsafe {
write(self.globals write(
.data self.globals.data.as_mut_ptr().offset(
.as_mut_ptr() globalinfo.offset as isize,
.offset(globalinfo.offset as isize) as ) as *mut i64,
*mut i64, val,
val) )
}, },
GlobalInit::F32Const(val) => unsafe { GlobalInit::F32Const(val) => unsafe {
write(self.globals write(
.data self.globals.data.as_mut_ptr().offset(
.as_mut_ptr() globalinfo.offset as isize,
.offset(globalinfo.offset as isize) as ) as *mut f32,
*mut f32, transmute(val),
transmute(val)) )
}, },
GlobalInit::F64Const(val) => unsafe { GlobalInit::F64Const(val) => unsafe {
write(self.globals write(
.data self.globals.data.as_mut_ptr().offset(
.as_mut_ptr() globalinfo.offset as isize,
.offset(globalinfo.offset as isize) as ) as *mut f64,
*mut f64, transmute(val),
transmute(val)) )
}, },
GlobalInit::Import() => { GlobalInit::Import() => {
// We don't initialize, this is inter-module linking // 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 ref_offset = self.globals.info[index].offset;
let size = globalinfo.global.ty.bytes(); let size = globalinfo.global.ty.bytes();
unsafe { unsafe {
let dst = self.globals let dst = self.globals.data.as_mut_ptr().offset(
.data globalinfo.offset as isize,
.as_mut_ptr() );
.offset(globalinfo.offset as isize);
let src = self.globals.data.as_ptr().offset(ref_offset as isize); let src = self.globals.data.as_ptr().offset(ref_offset as isize);
copy_nonoverlapping(src, dst, size as usize) copy_nonoverlapping(src, dst, size as usize)
} }
@@ -261,12 +273,10 @@ impl WasmRuntime for StandaloneRuntime {
} }
fn declare_global(&mut self, global: Global) { fn declare_global(&mut self, global: Global) {
debug_assert!(!self.instantiated); debug_assert!(!self.instantiated);
self.globals self.globals.info.push(GlobalInfo {
.info global: global,
.push(GlobalInfo { offset: 0,
global: global, });
offset: 0,
});
} }
fn declare_table(&mut self, table: Table) { fn declare_table(&mut self, table: Table) {
debug_assert!(!self.instantiated); debug_assert!(!self.instantiated);
@@ -274,17 +284,18 @@ impl WasmRuntime for StandaloneRuntime {
elements_vec.resize(table.size as usize, TableElement::Trap()); elements_vec.resize(table.size as usize, TableElement::Trap());
let mut addresses_vec = Vec::with_capacity(table.size as usize); let mut addresses_vec = Vec::with_capacity(table.size as usize);
addresses_vec.resize(table.size as usize, 0); addresses_vec.resize(table.size as usize, 0);
self.tables self.tables.push(TableData {
.push(TableData { info: table,
info: table, data: addresses_vec,
data: addresses_vec, elements: elements_vec,
elements: elements_vec, });
});
} }
fn declare_table_elements(&mut self, fn declare_table_elements(
table_index: TableIndex, &mut self,
offset: usize, table_index: TableIndex,
elements: &[FunctionIndex]) { offset: usize,
elements: &[FunctionIndex],
) {
debug_assert!(!self.instantiated); debug_assert!(!self.instantiated);
for (i, elt) in elements.iter().enumerate() { for (i, elt) in elements.iter().enumerate() {
self.tables[table_index].elements[offset as usize + i] = TableElement::Function(*elt); self.tables[table_index].elements[offset as usize + i] = TableElement::Function(*elt);
@@ -294,17 +305,17 @@ impl WasmRuntime for StandaloneRuntime {
debug_assert!(!self.instantiated); debug_assert!(!self.instantiated);
let mut memory_vec = Vec::with_capacity(memory.pages_count as usize * PAGE_SIZE); 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); memory_vec.resize(memory.pages_count as usize * PAGE_SIZE, 0);
self.memories self.memories.push(MemoryData {
.push(MemoryData { info: memory,
info: memory, data: memory_vec,
data: memory_vec, });
});
} }
fn declare_data_initialization(&mut self, fn declare_data_initialization(
memory_index: MemoryIndex, &mut self,
offset: usize, memory_index: MemoryIndex,
data: &[u8]) offset: usize,
-> Result<(), String> { data: &[u8],
) -> Result<(), String> {
if offset + data.len() > self.memories[memory_index].info.pages_count * PAGE_SIZE { if offset + data.len() > self.memories[memory_index].info.pages_count * PAGE_SIZE {
return Err(String::from("initialization data out of bounds")); 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. /// Returns a slice of the contents of allocated linear memory.
pub fn inspect_memory(&self, memory_index: usize, address: usize, len: usize) -> &[u8] { pub fn inspect_memory(&self, memory_index: usize, address: usize, len: usize) -> &[u8] {
&self.memories &self.memories
.get(memory_index) .get(memory_index)
.expect(format!("no memory for index {}", memory_index).as_str()) .expect(format!("no memory for index {}", memory_index).as_str())
.data .data
[address..address + len] [address..address + len]
} }
/// Shows the value of a global variable. /// Shows the value of a global variable.
pub fn inspect_global(&self, global_index: usize) -> &[u8] { pub fn inspect_global(&self, global_index: usize) -> &[u8] {
let (offset, len) = (self.globals.info[global_index].offset, let (offset, len) = (
self.globals.info[global_index].global.ty.bytes() as usize); self.globals.info[global_index].offset,
self.globals.info[global_index].global.ty.bytes() as usize,
);
&self.globals.data[offset..offset + len] &self.globals.data[offset..offset + len]
} }
} }

View File

@@ -101,7 +101,9 @@ fn read_wasm_file(path: PathBuf) -> Result<Vec<u8>, io::Error> {
fn main() { fn main() {
let args: Args = Docopt::new(USAGE) 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()); .unwrap_or_else(|e| e.exit());
let mut terminal = term::stdout().unwrap(); let mut terminal = term::stdout().unwrap();
for filename in args.arg_file.iter() { 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()) .arg(file_path.to_str().unwrap())
.output() .output()
.or_else(|e| if let io::ErrorKind::NotFound = e.kind() { .or_else(|e| if let io::ErrorKind::NotFound = e.kind() {
return Err(String::from("wast2wasm not found")); return Err(String::from("wast2wasm not found"));
} else { } else {
return Err(String::from(e.description())); return Err(String::from(e.description()));
}) })
.unwrap(); .unwrap();
match read_wasm_file(file_path) { match read_wasm_file(file_path) {
Ok(data) => data, Ok(data) => data,
@@ -312,16 +314,15 @@ fn handle_module(args: &Args, path: PathBuf, name: String) -> Result<(), String>
if split.len() != 3 { if split.len() != 3 {
break; break;
} }
let memory = standalone_runtime let memory = standalone_runtime.inspect_memory(
.inspect_memory(str::parse(split[0]).unwrap(), str::parse(split[0]).unwrap(),
str::parse(split[1]).unwrap(), str::parse(split[1]).unwrap(),
str::parse(split[2]).unwrap()); str::parse(split[2]).unwrap(),
let mut s = memory );
.iter() let mut s = memory.iter().fold(String::from("#"), |mut acc, byte| {
.fold(String::from("#"), |mut acc, byte| { acc.push_str(format!("{:02x}_", byte).as_str());
acc.push_str(format!("{:02x}_", byte).as_str()); acc
acc });
});
s.pop(); s.pop();
println!("{}", s); 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. // Prints out a Wasm module, and for each function the corresponding translation in Cretonne IL.
fn pretty_print_translation(filename: &String, fn pretty_print_translation(
data: &Vec<u8>, filename: &String,
translation: &TranslationResult, data: &Vec<u8>,
writer_wast: &mut Write, translation: &TranslationResult,
writer_cretonne: &mut Write) writer_wast: &mut Write,
-> Result<(), io::Error> { writer_cretonne: &mut Write,
) -> Result<(), io::Error> {
let mut terminal = term::stdout().unwrap(); let mut terminal = term::stdout().unwrap();
let mut parser = Parser::new(data.as_slice()); let mut parser = Parser::new(data.as_slice());
let mut parser_writer = Writer::new(writer_wast); let mut parser_writer = Writer::new(writer_wast);
let imports_count = translation let imports_count = translation.functions.iter().fold(0, |acc, &ref f| match f {
.functions &FunctionTranslation::Import() => acc + 1,
.iter() &FunctionTranslation::Code { .. } => acc,
.fold(0, |acc, &ref f| match f { });
&FunctionTranslation::Import() => acc + 1,
&FunctionTranslation::Code { .. } => acc,
});
match parser.read() { match parser.read() {
s @ &ParserState::BeginWasm { .. } => parser_writer.write(&s)?, s @ &ParserState::BeginWasm { .. } => parser_writer.write(&s)?,
_ => panic!("modules should begin properly"), _ => panic!("modules should begin properly"),
@@ -370,10 +369,12 @@ fn pretty_print_translation(filename: &String,
match parser.read() { match parser.read() {
s @ &ParserState::BeginFunctionBody { .. } => { s @ &ParserState::BeginFunctionBody { .. } => {
terminal.fg(term::color::BLUE).unwrap(); terminal.fg(term::color::BLUE).unwrap();
write!(writer_cretonne, write!(
"====== Function No. {} of module \"{}\" ======\n", writer_cretonne,
function_index, "====== Function No. {} of module \"{}\" ======\n",
filename)?; function_index,
filename
)?;
terminal.fg(term::color::CYAN).unwrap(); terminal.fg(term::color::CYAN).unwrap();
write!(writer_cretonne, "Wast ---------->\n")?; write!(writer_cretonne, "Wast ---------->\n")?;
terminal.reset().unwrap(); terminal.reset().unwrap();
@@ -398,13 +399,13 @@ fn pretty_print_translation(filename: &String,
}; };
} }
} }
let mut function_string = let mut function_string = format!(
format!(" {}", " {}",
match translation.functions[function_index + imports_count] { match translation.functions[function_index + imports_count] {
FunctionTranslation::Code { ref il, .. } => il, FunctionTranslation::Code { ref il, .. } => il,
FunctionTranslation::Import() => panic!("should not happen"), FunctionTranslation::Import() => panic!("should not happen"),
} }.display(None)
.display(None)); );
function_string.pop(); function_string.pop();
let function_str = str::replace(function_string.as_str(), "\n", "\n "); let function_str = str::replace(function_string.as_str(), "\n", "\n ");
terminal.fg(term::color::CYAN).unwrap(); terminal.fg(term::color::CYAN).unwrap();
@@ -422,17 +423,20 @@ fn pretty_print_translation(filename: &String,
} }
/// Pretty-print a verifier error. /// Pretty-print a verifier error.
pub fn pretty_verifier_error(func: &ir::Function, pub fn pretty_verifier_error(
isa: Option<&TargetIsa>, func: &ir::Function,
err: verifier::Error) isa: Option<&TargetIsa>,
-> String { err: verifier::Error,
) -> String {
let msg = err.to_string(); let msg = err.to_string();
let str1 = match err.location { let str1 = match err.location {
AnyEntity::Inst(inst) => { AnyEntity::Inst(inst) => {
format!("{}\n{}: {}\n\n", format!(
msg, "{}\n{}: {}\n\n",
inst, msg,
func.dfg.display_inst(inst, isa)) inst,
func.dfg.display_inst(inst, isa)
)
} }
_ => String::from(format!("{}\n", msg)), _ => String::from(format!("{}\n", msg)),
}; };