Added support for global value offsets

This commit depends on this PR landing on cranelift:
https://github.com/CraneStation/cranelift/pull/612
This commit is contained in:
Syrus Akbary
2018-11-18 20:22:18 -08:00
parent 998d7294f0
commit 9f561db90b
7 changed files with 411 additions and 352 deletions

View File

@ -9,7 +9,7 @@
use cranelift_codegen::ir::LibCall;
use cranelift_codegen::{binemit, Context};
use cranelift_entity::EntityRef;
use cranelift_wasm::{FuncIndex, GlobalInit};
use cranelift_wasm::{FuncIndex, GlobalInit, GlobalIndex};
use cranelift_codegen::isa::TargetIsa;
use region;
use std::iter::Iterator;
@ -22,8 +22,7 @@ use super::super::common::slice::{BoundedSlice, UncheckedSlice};
use super::errors::ErrorKind;
use super::import_object::{ImportObject, ImportValue};
use super::memory::LinearMemory;
use super::module::Export;
use super::module::Module;
use super::module::{Export, Exportable, Module};
use super::relocation::{Reloc, RelocSink, RelocationType};
use super::math_intrinsics;
@ -145,9 +144,6 @@ impl Instance {
let mut functions: Vec<Vec<u8>> = Vec::new();
let mut import_functions: Vec<*const u8> = Vec::new();
let mut imported_memories: Vec<LinearMemory> = Vec::new();
let mut imported_tables: Vec<Vec<usize>> = Vec::new();
debug!("Instance - Instantiating functions");
// Instantiate functions
{
@ -295,45 +291,81 @@ impl Instance {
}
}
// Looping through and getting the imported objects
for (_key, value) in import_object.map {
match value {
ImportValue::Memory(value) =>
imported_memories.push(value),
ImportValue::Table(value) =>
imported_tables.push(value),
_ => (),
debug!("Instance - Instantiating globals");
// Instantiate Globals
let globals_data = {
let globals_count = module.info.globals.len();
// Allocate the underlying memory and initialize it to zeros
let globals_data_size = globals_count * 8;
globals.resize(globals_data_size, 0);
// cast the globals slice to a slice of i64.
let globals_data = unsafe {
slice::from_raw_parts_mut(globals.as_mut_ptr() as *mut i64, globals_count)
};
for (i, global) in module.info.globals.iter().enumerate() {
let Exportable {entity, import_name, ..} = global;
let value: i64 = match entity.initializer {
GlobalInit::I32Const(n) => n as _,
GlobalInit::I64Const(n) => n,
GlobalInit::F32Const(f) => f as _, // unsafe { mem::transmute(f as f64) },
GlobalInit::F64Const(f) => f as _, // unsafe { mem::transmute(f) },
GlobalInit::GlobalRef(_global_index) => {
unimplemented!("GlobalInit::GlobalRef is not yet supported")
}
GlobalInit::Import() => {
let (module_name, field_name) = import_name.as_ref().expect("Expected a import name for the global import");
let imported = import_object.get(&module_name.as_str(), &field_name.as_str());
match imported {
Some(ImportValue::Global(value)) => {
*value
},
_ => panic!("Imported global value was not provided {:?} ({}.{})", imported, module_name, field_name)
}
}
};
globals_data[i] = value;
}
}
globals_data
};
debug!("Instance - Instantiating tables");
// Instantiate tables
{
// Reserve space for tables
tables.reserve_exact(imported_tables.len() + module.info.tables.len());
// Get imported tables
for table in imported_tables {
tables.push(table);
}
tables.reserve_exact(module.info.tables.len());
// Get tables in module
for table in &module.info.tables {
let len = table.entity.size;
let mut v = Vec::with_capacity(len);
v.resize(len, 0);
tables.push(v);
let table: Vec<usize> = match table.import_name.as_ref() {
Some((module_name, field_name)) => {
let imported = import_object.get(&module_name.as_str(), &field_name.as_str());
match imported {
Some(ImportValue::Table(t)) => {
t.to_vec()
},
_ => panic!("Imported table was not provided {:?} ({}.{})", imported, module_name, field_name)
}
},
None => {
let len = table.entity.size;
let mut v = Vec::with_capacity(len);
v.resize(len, 0);
v
}
};
tables.push(table);
}
// instantiate tables
for table_element in &module.info.table_elements {
// TODO: We shouldn't assert here since we are returning a Result<Instance, ErrorKind>
assert!(
table_element.base.is_none(),
"globalvalue base not supported yet."
);
let base = 0;
let base = match table_element.base {
Some(global_index) => {
globals_data[global_index.index()] as usize
},
None => 0
};
let table = &mut tables[table_element.table_index.index()];
for (i, func_index) in table_element.elements.iter().enumerate() {
@ -343,6 +375,7 @@ impl Instance {
// let func_index = *elem_index - module.info.imported_funcs.len() as u32;
// let func_addr = functions[func_index.index()].as_ptr();
println!("TABLE LENGTH: {}", table.len());
let func_addr = get_function_addr(&func_index, &import_functions, &functions);
table[base + table_element.offset + i] = func_addr as _;
}
@ -353,12 +386,7 @@ impl Instance {
// Instantiate memories
{
// Reserve space for memories
memories.reserve_exact(imported_memories.len() + module.info.memories.len());
// Get imported memories
for memory in imported_memories {
memories.push(memory);
}
memories.reserve_exact(module.info.memories.len());
// Get memories in module
for memory in &module.info.memories {
@ -379,41 +407,6 @@ impl Instance {
}
}
debug!("Instance - Instantiating globals");
// TODO: Fix globals import
// Instantiate Globals
{
let globals_count = module.info.globals.len();
// Allocate the underlying memory and initialize it to zeros
let globals_data_size = globals_count * 8;
globals.resize(globals_data_size, 0);
// cast the globals slice to a slice of i64.
let globals_data = unsafe {
slice::from_raw_parts_mut(globals.as_mut_ptr() as *mut i64, globals_count)
};
for (i, global) in module.info.globals.iter().enumerate() {
let value: i64 = match global.entity.initializer {
GlobalInit::I32Const(n) => n as _,
GlobalInit::I64Const(n) => n,
GlobalInit::F32Const(f) => f as _, // unsafe { mem::transmute(f as f64) },
GlobalInit::F64Const(f) => f as _, // unsafe { mem::transmute(f) },
GlobalInit::GlobalRef(_global_index) => {
unimplemented!("GlobalInit::GlobalRef is not yet supported")
}
GlobalInit::Import() => {
// Right now (because there is no module/field fields on the Import
// https://github.com/CraneStation/cranelift/blob/5cabce9b58ff960534d4017fad11f2e78c72ceab/lib/wasm/src/sections_translator.rs#L90-L99 )
// It's impossible to know where to take the global from.
// This should be fixed in Cranelift itself.
unimplemented!("GlobalInit::Import is not yet supported")
}
};
globals_data[i] = value;
}
}
let start_func: Option<FuncIndex> =
module
.info