Update for Cretonne API changes.

This commit is contained in:
Dan Gohman
2017-10-10 10:24:15 -07:00
parent 142b17a3f0
commit 3d6f0f7045
3 changed files with 159 additions and 93 deletions

View File

@@ -72,8 +72,7 @@ pub fn compile_module(
runtime: &wasmstandalone_runtime::Runtime, runtime: &wasmstandalone_runtime::Runtime,
) -> Result<ExecutableCode, String> { ) -> Result<ExecutableCode, String> {
debug_assert!( debug_assert!(
trans_result.start_index.is_none() || runtime.start_func.is_none() || runtime.start_func.unwrap() >= runtime.imported_funcs.len(),
trans_result.start_index.unwrap() >= runtime.imported_funcs.len(),
"imported start functions not supported yet" "imported start functions not supported yet"
); );
@@ -101,7 +100,7 @@ pub fn compile_module(
} }
relocate(&functions_metatada, &mut functions_code, runtime); relocate(&functions_metatada, &mut functions_code, runtime);
// 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 runtime.start_func {
None => Err(String::from( None => Err(String::from(
"No start function defined, aborting execution", "No start function defined, aborting execution",
)), )),

View File

@@ -53,8 +53,7 @@ pub fn emit_module(
runtime: &wasmstandalone_runtime::Runtime, runtime: &wasmstandalone_runtime::Runtime,
) -> Result<(), String> { ) -> Result<(), String> {
debug_assert!( debug_assert!(
trans_result.start_index.is_none() || runtime.start_func.is_none() || runtime.start_func.unwrap() >= runtime.imported_funcs.len(),
trans_result.start_index.unwrap() >= runtime.imported_funcs.len(),
"imported start functions not supported yet" "imported start functions not supported yet"
); );

View File

@@ -22,6 +22,7 @@ use cretonne::entity::EntityMap;
use std::mem::transmute; use std::mem::transmute;
use std::ptr::copy_nonoverlapping; use std::ptr::copy_nonoverlapping;
use std::ptr::write; use std::ptr::write;
use std::collections::HashMap;
/// Runtime state of a WebAssembly table element. /// Runtime state of a WebAssembly table element.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@@ -64,6 +65,18 @@ pub struct MemoryData {
const PAGE_SIZE: usize = 65536; const PAGE_SIZE: usize = 65536;
/// An entity to export.
pub enum Export {
/// Function export.
Function(FunctionIndex),
/// Table export.
Table(TableIndex),
/// Memory export.
Memory(MemoryIndex),
/// Global export.
Global(GlobalIndex),
}
/// Object containing the standalone runtime information. To be passed after creation as argument /// Object containing the standalone runtime information. To be passed after creation as argument
/// to `cton_wasm::translatemodule`. /// to `cton_wasm::translatemodule`.
pub struct Runtime { pub struct Runtime {
@@ -72,17 +85,24 @@ pub struct Runtime {
/// Unprocessed signatures exactly as provided by `declare_signature()`. /// Unprocessed signatures exactly as provided by `declare_signature()`.
signatures: Vec<ir::Signature>, signatures: Vec<ir::Signature>,
/// Types of functions, imported and local.
func_types: Vec<SignatureIndex>,
/// Names of imported functions. /// Names of imported functions.
pub imported_funcs: Vec<ir::FunctionName>, pub imported_funcs: Vec<(String, String)>,
/// Types of functions, imported and local.
functions: Vec<SignatureIndex>,
/// WebAssembly tables.
pub tables: Vec<TableData>,
/// WebAssembly linear memories.
pub memories: Vec<MemoryData>,
/// WebAssembly global variables. /// WebAssembly global variables.
pub globals: GlobalsData, pub globals: GlobalsData,
/// WebAssembly tables.
pub tables: Vec<TableData>, /// Exported entities.
/// WebAssembly linear memories. pub exports: HashMap<String, Export>,
pub memories: Vec<MemoryData>,
instantiated: bool, instantiated: bool,
@@ -93,6 +113,9 @@ pub struct Runtime {
pub func_indices: EntityMap<FuncRef, FunctionIndex>, pub func_indices: EntityMap<FuncRef, FunctionIndex>,
the_heap: PackedOption<ir::Heap>, the_heap: PackedOption<ir::Heap>,
/// The module "start" function, if present.
pub start_func: Option<FunctionIndex>,
} }
impl Runtime { impl Runtime {
@@ -106,19 +129,21 @@ impl Runtime {
Self { Self {
flags, flags,
signatures: Vec::new(), signatures: Vec::new(),
func_types: Vec::new(),
imported_funcs: Vec::new(), imported_funcs: Vec::new(),
functions: Vec::new(),
tables: Vec::new(),
memories: Vec::new(),
globals: GlobalsData { globals: GlobalsData {
data: Vec::new(), data: Vec::new(),
info: Vec::new(), info: Vec::new(),
}, },
tables: Vec::new(), exports: HashMap::new(),
memories: Vec::new(),
instantiated: false, instantiated: false,
has_current_memory: None, has_current_memory: None,
has_grow_memory: None, has_grow_memory: None,
func_indices: EntityMap::new(), func_indices: EntityMap::new(),
the_heap: PackedOption::default(), the_heap: PackedOption::default(),
start_func: None,
} }
} }
@@ -183,14 +208,9 @@ impl FuncEnvironment for Runtime {
} }
fn make_direct_func(&mut self, func: &mut ir::Function, index: FunctionIndex) -> ir::FuncRef { fn make_direct_func(&mut self, func: &mut ir::Function, index: FunctionIndex) -> ir::FuncRef {
let sigidx = self.func_types[index]; let sigidx = self.functions[index];
let signature = func.import_signature(self.signatures[sigidx].clone()); let signature = func.import_signature(self.signatures[sigidx].clone());
let name = self.get_func_name(index);
let name = match self.imported_funcs.get(index) {
Some(name) => name.clone(),
None => ir::FunctionName::new(format!("localfunc{}", index)),
};
let func_ref = func.import_function(ir::ExtFuncData { name, signature }); let func_ref = func.import_function(ir::ExtFuncData { name, signature });
self.func_indices[func_ref] = index; self.func_indices[func_ref] = index;
@@ -290,6 +310,10 @@ impl FuncEnvironment for Runtime {
/// 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 Runtime { impl WasmRuntime for Runtime {
fn get_func_name(&self, func_index: FunctionIndex) -> cretonne::ir::FunctionName {
ir::FunctionName::new(format!("wasm_0x{:x}", func_index))
}
fn declare_signature(&mut self, sig: &ir::Signature) { fn declare_signature(&mut self, sig: &ir::Signature) {
let mut sig = sig.clone(); let mut sig = sig.clone();
sig.argument_types.push(ArgumentType { sig.argument_types.push(ArgumentType {
@@ -306,24 +330,128 @@ impl WasmRuntime for Runtime {
&self.signatures[sig_index] &self.signatures[sig_index]
} }
fn declare_func_import(&mut self, sig_index: SignatureIndex, module: &[u8], field: &[u8]) { fn declare_func_import(&mut self, sig_index: SignatureIndex, module: &str, field: &str) {
debug_assert_eq!( debug_assert_eq!(
self.func_types.len(), self.functions.len(),
self.imported_funcs.len(), self.imported_funcs.len(),
"Imported functions must be declared first" "Imported functions must be declared first"
); );
self.func_types.push(sig_index); self.functions.push(sig_index);
// TODO: name_fold and concatenation with '_' are lossy; figure out something better. self.imported_funcs.push((
let mut name = Vec::new(); String::from(module),
name.extend(module.iter().cloned().map(name_fold)); String::from(field),
name.push(b'_'); ));
name.extend(field.iter().cloned().map(name_fold)); }
self.imported_funcs.push(ir::FunctionName::new(name));
fn get_num_func_imports(&self) -> usize {
self.imported_funcs.len()
} }
fn declare_func_type(&mut self, sig_index: SignatureIndex) { fn declare_func_type(&mut self, sig_index: SignatureIndex) {
self.func_types.push(sig_index); self.functions.push(sig_index);
}
fn get_func_type(&self, func_index: FunctionIndex) -> usize {
self.functions[func_index]
}
fn declare_global(&mut self, global: Global) {
debug_assert!(!self.instantiated);
let index = self.globals.info.len() as GlobalIndex;
self.globals.info.push(GlobalInfo {
global: global,
offset: Self::global_offset(index),
});
}
fn get_global(&self, global_index: GlobalIndex) -> &cton_wasm::Global {
&self.globals.info[global_index].global
}
fn declare_table(&mut self, table: Table) {
debug_assert!(!self.instantiated);
let mut elements_vec = Vec::with_capacity(table.size);
elements_vec.resize(table.size, TableElement::Trap());
let mut addresses_vec = Vec::with_capacity(table.size);
addresses_vec.resize(table.size, 0);
self.tables.push(TableData {
info: table,
data: addresses_vec,
elements: elements_vec,
});
}
fn declare_table_elements(
&mut self,
table_index: TableIndex,
base: Option<GlobalIndex>,
offset: usize,
elements: &[FunctionIndex],
) {
debug_assert!(base.is_none(), "global-value offsets not supported yet");
debug_assert!(!self.instantiated);
for (i, elt) in elements.iter().enumerate() {
self.tables[table_index].elements[offset + i] = TableElement::Function(*elt);
}
}
fn declare_memory(&mut self, memory: Memory) {
debug_assert!(!self.instantiated);
let mut memory_vec = Vec::with_capacity(memory.pages_count * PAGE_SIZE);
memory_vec.resize(memory.pages_count * PAGE_SIZE, 0);
self.memories.push(MemoryData {
info: memory,
data: memory_vec,
});
}
fn declare_data_initialization(
&mut self,
memory_index: MemoryIndex,
base: Option<GlobalIndex>,
offset: usize,
data: &[u8],
) {
debug_assert!(base.is_none(), "global-value offsets not supported yet");
debug_assert!(
offset + data.len() <= self.memories[memory_index].info.pages_count * PAGE_SIZE,
"initialization data out of bounds"
);
self.memories[memory_index].data[offset..offset + data.len()].copy_from_slice(data);
}
fn declare_func_export(&mut self, func_index: FunctionIndex, name: &str) {
self.exports.insert(
String::from(name),
Export::Function(func_index),
);
}
fn declare_table_export(&mut self, table_index: TableIndex, name: &str) {
self.exports.insert(
String::from(name),
Export::Table(table_index),
);
}
fn declare_memory_export(&mut self, memory_index: MemoryIndex, name: &str) {
self.exports.insert(
String::from(name),
Export::Memory(memory_index),
);
}
fn declare_global_export(&mut self, global_index: GlobalIndex, name: &str) {
self.exports.insert(
String::from(name),
Export::Global(global_index),
);
}
fn declare_start_func(&mut self, func_index: FunctionIndex) {
debug_assert!(self.start_func.is_none());
self.start_func = Some(func_index);
} }
fn begin_translation(&mut self) { fn begin_translation(&mut self) {
@@ -385,64 +513,13 @@ impl WasmRuntime for Runtime {
} }
} }
} }
fn next_function(&mut self) { fn next_function(&mut self) {
self.has_current_memory = None; self.has_current_memory = None;
self.has_grow_memory = None; self.has_grow_memory = None;
self.func_indices.clear(); self.func_indices.clear();
self.the_heap = PackedOption::default(); self.the_heap = PackedOption::default();
} }
fn declare_global(&mut self, global: Global) {
debug_assert!(!self.instantiated);
let index = self.globals.info.len() as GlobalIndex;
self.globals.info.push(GlobalInfo {
global: global,
offset: Self::global_offset(index),
});
}
fn declare_table(&mut self, table: Table) {
debug_assert!(!self.instantiated);
let mut elements_vec = Vec::with_capacity(table.size);
elements_vec.resize(table.size, TableElement::Trap());
let mut addresses_vec = Vec::with_capacity(table.size);
addresses_vec.resize(table.size, 0);
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],
) {
debug_assert!(!self.instantiated);
for (i, elt) in elements.iter().enumerate() {
self.tables[table_index].elements[offset + i] = TableElement::Function(*elt);
}
}
fn declare_memory(&mut self, memory: Memory) {
debug_assert!(!self.instantiated);
let mut memory_vec = Vec::with_capacity(memory.pages_count * PAGE_SIZE);
memory_vec.resize(memory.pages_count * PAGE_SIZE, 0);
self.memories.push(MemoryData {
info: memory,
data: memory_vec,
});
}
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"));
}
self.memories[memory_index].data[offset..offset + data.len()].copy_from_slice(data);
Ok(())
}
} }
/// Convenience functions for the user to be called after execution for debug purposes. /// Convenience functions for the user to be called after execution for debug purposes.
@@ -464,12 +541,3 @@ impl Runtime {
&self.globals.data[offset..offset + len] &self.globals.data[offset..offset + len]
} }
} }
// Generate characters suitable for printable `FuncName`s.
fn name_fold(c: u8) -> u8 {
if (c as char).is_alphanumeric() {
c
} else {
b'_'
}
}