runtime type injection implemented #10

This commit is contained in:
fro
2017-09-25 20:14:46 +03:00
parent a6b6d75be0
commit 9be2a5bf31
5 changed files with 67 additions and 2 deletions
+3
View File
@@ -1,5 +1,6 @@
extern crate parity_wasm;
extern crate env_logger;
extern crate byteorder;
#[macro_use] extern crate log;
#[macro_use] extern crate lazy_static;
@@ -12,6 +13,7 @@ mod logger;
mod ext;
mod pack;
mod nondeterminism_check;
mod runtime_type;
pub use optimizer::{optimize, Error as OptimizerError};
pub use gas::inject_gas_counter;
@@ -19,3 +21,4 @@ pub use logger::init_log;
pub use ext::externalize;
pub use pack::pack_instance;
pub use nondeterminism_check::is_deterministic;
pub use runtime_type::inject_runtime_type;
+1 -1
View File
@@ -120,7 +120,7 @@ mod tests {
#[test]
fn nondeterminism_not() {
let module = builder::module()
.function().signature().return_type().f32().build()
.function().signature().return_type().i32().build()
.body()
.with_opcodes(elements::Opcodes::new(
vec![
+43
View File
@@ -0,0 +1,43 @@
use parity_wasm::{elements, builder};
use self::elements::{ Module, GlobalEntry, External, ExportEntry, GlobalType, ValueType, InitExpr, Opcode, Internal };
use byteorder::{ LittleEndian, ByteOrder };
pub fn inject_runtime_type(module: Module, runtime_type: &[u8], runtime_version: u32) -> Module {
let runtime_type: u32 = LittleEndian::read_u32(&runtime_type);
let globals_count: u32 = match module.global_section() {
Some(ref section) => section.entries().len() as u32,
None => 0
};
let imported_globals_count: u32 = match module.import_section() {
Some(ref section) => section.entries().iter().filter(|e| match *e.external() {
External::Global(ref _a) => true,
_ => false
}).count() as u32,
None => 0
};
let total_globals_count: u32 = globals_count + imported_globals_count;
builder::from_module(module)
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const(runtime_type as i32), Opcode::End])))
.with_export(ExportEntry::new("RUNTIME_TYPE".into(), Internal::Global(total_globals_count)))
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const(runtime_version as i32), Opcode::End])))
.with_export(ExportEntry::new("RUNTIME_VERSION".into(), Internal::Global(total_globals_count + 1)))
.build()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_injects() {
let mut module = builder::module()
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const(42 as i32)])))
.build();
module = inject_runtime_type(module, b"emcc", 1);
let global_section = module.global_section().expect("Global section expected");
assert_eq!(3, global_section.entries().len());
let export_section = module.export_section().expect("Export section expected");
assert!(export_section.entries().iter().find(|e| e.field() == "RUNTIME_TYPE" ).is_some());
assert!(export_section.entries().iter().find(|e| e.field() == "RUNTIME_VERSION" ).is_some());
}
}