Format with rustfmt 0.9.0.
This commit is contained in:
@@ -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"));
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,9 @@ pub fn compile_module(trans_result: &TranslationResult) -> Result<ExecutableCode
|
|||||||
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,
|
||||||
@@ -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.as_ptr(),
|
||||||
code_buf.len(),
|
code_buf.len(),
|
||||||
Protection::ReadWriteExecute) {
|
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
|
||||||
@@ -216,10 +222,10 @@ fn relocate(functions_metatada: &Vec<FunctionMetaData>, functions_code: &mut Vec
|
|||||||
.offset(offset as isize + 4) as
|
.offset(offset as isize + 4) as
|
||||||
isize;
|
isize;
|
||||||
let target_ebb_address: isize =
|
let target_ebb_address: isize =
|
||||||
functions_code[func_index]
|
functions_code[func_index].as_ptr().offset(
|
||||||
.as_ptr()
|
il_func.offsets[ebb] as
|
||||||
.offset(il_func.offsets[ebb] as isize) as
|
isize,
|
||||||
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(
|
||||||
|
func: &Function,
|
||||||
isa: Option<&TargetIsa>,
|
isa: Option<&TargetIsa>,
|
||||||
err: verifier::Error)
|
err: verifier::Error,
|
||||||
-> String {
|
) -> 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) => {
|
||||||
|
|||||||
@@ -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(
|
||||||
|
&self,
|
||||||
builder: &mut FunctionBuilder<Local>,
|
builder: &mut FunctionBuilder<Local>,
|
||||||
global_index: GlobalIndex)
|
global_index: GlobalIndex,
|
||||||
-> Value {
|
) -> 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(
|
||||||
|
&self,
|
||||||
builder: &mut FunctionBuilder<Local>,
|
builder: &mut FunctionBuilder<Local>,
|
||||||
global_index: GlobalIndex,
|
global_index: GlobalIndex,
|
||||||
val: Value) {
|
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,23 +99,24 @@ 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(
|
||||||
|
&self,
|
||||||
builder: &mut FunctionBuilder<Local>,
|
builder: &mut FunctionBuilder<Local>,
|
||||||
memory_index: MemoryIndex)
|
memory_index: MemoryIndex,
|
||||||
-> Value {
|
) -> 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(
|
||||||
|
&mut self,
|
||||||
builder: &mut FunctionBuilder<Local>,
|
builder: &mut FunctionBuilder<Local>,
|
||||||
pages: Value)
|
pages: Value,
|
||||||
-> 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)],
|
||||||
@@ -137,8 +141,7 @@ impl WasmRuntime for StandaloneRuntime {
|
|||||||
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"),
|
||||||
@@ -150,26 +153,31 @@ impl WasmRuntime for StandaloneRuntime {
|
|||||||
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>(
|
||||||
|
&self,
|
||||||
builder: &'a mut FunctionBuilder<Local>,
|
builder: &'a mut FunctionBuilder<Local>,
|
||||||
sig_ref: SigRef,
|
sig_ref: SigRef,
|
||||||
index_val: Value,
|
index_val: Value,
|
||||||
call_args: &[Value])
|
call_args: &[Value],
|
||||||
-> &'a [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,
|
&[],
|
||||||
|
);
|
||||||
|
builder.ins().br_icmp(
|
||||||
|
IntCC::UnsignedGreaterThanOrEqual,
|
||||||
index_val,
|
index_val,
|
||||||
size_val,
|
size_val,
|
||||||
trap_ebb,
|
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,9 +273,7 @@ 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
|
|
||||||
.push(GlobalInfo {
|
|
||||||
global: global,
|
global: global,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
});
|
});
|
||||||
@@ -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(
|
||||||
|
&mut self,
|
||||||
table_index: TableIndex,
|
table_index: TableIndex,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
elements: &[FunctionIndex]) {
|
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(
|
||||||
|
&mut self,
|
||||||
memory_index: MemoryIndex,
|
memory_index: MemoryIndex,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
data: &[u8])
|
data: &[u8],
|
||||||
-> Result<(), String> {
|
) -> 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"));
|
||||||
}
|
}
|
||||||
@@ -325,8 +336,10 @@ impl StandaloneRuntime {
|
|||||||
}
|
}
|
||||||
/// 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]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
54
src/main.rs
54
src/main.rs
@@ -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() {
|
||||||
@@ -312,13 +314,12 @@ 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
|
||||||
});
|
});
|
||||||
@@ -334,19 +335,17 @@ 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(
|
||||||
|
filename: &String,
|
||||||
data: &Vec<u8>,
|
data: &Vec<u8>,
|
||||||
translation: &TranslationResult,
|
translation: &TranslationResult,
|
||||||
writer_wast: &mut Write,
|
writer_wast: &mut Write,
|
||||||
writer_cretonne: &mut Write)
|
writer_cretonne: &mut Write,
|
||||||
-> Result<(), io::Error> {
|
) -> 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
|
|
||||||
.iter()
|
|
||||||
.fold(0, |acc, &ref f| match f {
|
|
||||||
&FunctionTranslation::Import() => acc + 1,
|
&FunctionTranslation::Import() => acc + 1,
|
||||||
&FunctionTranslation::Code { .. } => acc,
|
&FunctionTranslation::Code { .. } => acc,
|
||||||
});
|
});
|
||||||
@@ -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!(
|
||||||
|
writer_cretonne,
|
||||||
"====== Function No. {} of module \"{}\" ======\n",
|
"====== Function No. {} of module \"{}\" ======\n",
|
||||||
function_index,
|
function_index,
|
||||||
filename)?;
|
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(
|
||||||
|
func: &ir::Function,
|
||||||
isa: Option<&TargetIsa>,
|
isa: Option<&TargetIsa>,
|
||||||
err: verifier::Error)
|
err: verifier::Error,
|
||||||
-> String {
|
) -> 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!(
|
||||||
|
"{}\n{}: {}\n\n",
|
||||||
msg,
|
msg,
|
||||||
inst,
|
inst,
|
||||||
func.dfg.display_inst(inst, isa))
|
func.dfg.display_inst(inst, isa)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
_ => String::from(format!("{}\n", msg)),
|
_ => String::from(format!("{}\n", msg)),
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user