mirror of
https://github.com/fluencelabs/wasm-utils
synced 2025-06-29 14:31:40 +00:00
Merge pull request #20 from paritytech/runtime-type-build
Runtime type injection implemention
This commit is contained in:
@ -10,6 +10,7 @@ env_logger = "0.4"
|
|||||||
lazy_static = "0.2"
|
lazy_static = "0.2"
|
||||||
clap = "2.24"
|
clap = "2.24"
|
||||||
glob = "0.2"
|
glob = "0.2"
|
||||||
|
byteorder = "1"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|
||||||
|
@ -76,6 +76,14 @@ fn main() {
|
|||||||
.arg(Arg::with_name("skip_alloc")
|
.arg(Arg::with_name("skip_alloc")
|
||||||
.help("Skip allocator externalizer step producing final wasm")
|
.help("Skip allocator externalizer step producing final wasm")
|
||||||
.long("skip-externalize"))
|
.long("skip-externalize"))
|
||||||
|
.arg(Arg::with_name("runtime_type")
|
||||||
|
.help("Injects RUNTIME_TYPE global export")
|
||||||
|
.takes_value(true)
|
||||||
|
.long("runtime-type"))
|
||||||
|
.arg(Arg::with_name("runtime_version")
|
||||||
|
.help("Injects RUNTIME_VERSION global export")
|
||||||
|
.takes_value(true)
|
||||||
|
.long("runtime-version"))
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let target_dir = matches.value_of("target").expect("is required; qed");
|
let target_dir = matches.value_of("target").expect("is required; qed");
|
||||||
@ -98,5 +106,15 @@ fn main() {
|
|||||||
wasm_utils::optimize(&mut module, vec!["_call", "setTempRet0"]).expect("Optimizer to finish without errors");
|
wasm_utils::optimize(&mut module, vec!["_call", "setTempRet0"]).expect("Optimizer to finish without errors");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(runtime_type) = matches.value_of("runtime_type") {
|
||||||
|
let runtime_type: &[u8] = runtime_type.as_bytes();
|
||||||
|
if runtime_type.len() != 4 {
|
||||||
|
panic!("--runtime-type should be equal to 4 bytes");
|
||||||
|
}
|
||||||
|
let runtime_version: u32 = matches.value_of("runtime_version").unwrap_or("1").parse()
|
||||||
|
.expect("--runtime-version should be a positive integer");
|
||||||
|
module = wasm_utils::inject_runtime_type(module, &runtime_type, runtime_version);
|
||||||
|
}
|
||||||
|
|
||||||
parity_wasm::serialize_to_file(&path, module).unwrap();
|
parity_wasm::serialize_to_file(&path, module).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
extern crate parity_wasm;
|
extern crate parity_wasm;
|
||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
|
extern crate byteorder;
|
||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
#[macro_use] extern crate lazy_static;
|
#[macro_use] extern crate lazy_static;
|
||||||
|
|
||||||
@ -12,6 +13,7 @@ mod logger;
|
|||||||
mod ext;
|
mod ext;
|
||||||
mod pack;
|
mod pack;
|
||||||
mod nondeterminism_check;
|
mod nondeterminism_check;
|
||||||
|
mod runtime_type;
|
||||||
|
|
||||||
pub use optimizer::{optimize, Error as OptimizerError};
|
pub use optimizer::{optimize, Error as OptimizerError};
|
||||||
pub use gas::inject_gas_counter;
|
pub use gas::inject_gas_counter;
|
||||||
@ -19,3 +21,4 @@ pub use logger::init_log;
|
|||||||
pub use ext::externalize;
|
pub use ext::externalize;
|
||||||
pub use pack::pack_instance;
|
pub use pack::pack_instance;
|
||||||
pub use nondeterminism_check::is_deterministic;
|
pub use nondeterminism_check::is_deterministic;
|
||||||
|
pub use runtime_type::inject_runtime_type;
|
||||||
|
@ -120,7 +120,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn nondeterminism_not() {
|
fn nondeterminism_not() {
|
||||||
let module = builder::module()
|
let module = builder::module()
|
||||||
.function().signature().return_type().f32().build()
|
.function().signature().return_type().i32().build()
|
||||||
.body()
|
.body()
|
||||||
.with_opcodes(elements::Opcodes::new(
|
.with_opcodes(elements::Opcodes::new(
|
||||||
vec![
|
vec![
|
||||||
|
43
src/runtime_type.rs
Normal file
43
src/runtime_type.rs
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user