test for pack added

This commit is contained in:
fro
2017-10-27 18:32:33 +03:00
parent 918c8485a4
commit 4a70824a88
4 changed files with 88 additions and 11 deletions

View File

@ -26,10 +26,6 @@ path = "ext/src/main.rs"
name = "wasm-gas" name = "wasm-gas"
path = "gas/src/main.rs" path = "gas/src/main.rs"
[[bin]]
name = "wasm-pack"
path = "pack/src/main.rs"
[[bin]] [[bin]]
name = "wasm-build" name = "wasm-build"
path = "build/src/main.rs" path = "build/src/main.rs"

View File

@ -12,8 +12,7 @@ use std::path::PathBuf;
use clap::{App, Arg}; use clap::{App, Arg};
use parity_wasm::elements; use parity_wasm::elements;
use wasm_utils::CREATE_SYMBOL; use wasm_utils::{CREATE_SYMBOL, CALL_SYMBOL, SET_TEMP_RET_SYMBOL};
use wasm_utils::CALL_SYMBOL;
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
@ -65,7 +64,7 @@ pub fn process_output(target_dir: &str, bin_name: &str) -> Result<(), Error> {
fn has_ctor(module: &elements::Module) -> bool { fn has_ctor(module: &elements::Module) -> bool {
if let Some(ref section) = module.export_section() { if let Some(ref section) = module.export_section() {
section.entries().iter().any(|e| CALL_SYMBOL == e.field()) section.entries().iter().any(|e| CREATE_SYMBOL == e.field())
} else { } else {
false false
} }
@ -128,7 +127,7 @@ fn main() {
let mut ctor_module = module.clone(); let mut ctor_module = module.clone();
if !matches.is_present("skip_optimization") { if !matches.is_present("skip_optimization") {
wasm_utils::optimize(&mut module, vec![CALL_SYMBOL, "setTempRet0"]).expect("Optimizer to finish without errors"); wasm_utils::optimize(&mut module, vec![CALL_SYMBOL, SET_TEMP_RET_SYMBOL]).expect("Optimizer to finish without errors");
} }
let raw_module = parity_wasm::serialize(module).expect("Failed to serialize module"); let raw_module = parity_wasm::serialize(module).expect("Failed to serialize module");
@ -138,7 +137,7 @@ fn main() {
// Otherwise it will just save an optimised raw_module // Otherwise it will just save an optimised raw_module
if has_ctor(&ctor_module) { if has_ctor(&ctor_module) {
if !matches.is_present("skip_optimization") { if !matches.is_present("skip_optimization") {
wasm_utils::optimize(&mut ctor_module, vec![CREATE_SYMBOL, "setTempRet0"]).expect("Optimizer to finish without errors"); wasm_utils::optimize(&mut ctor_module, vec![CREATE_SYMBOL, SET_TEMP_RET_SYMBOL]).expect("Optimizer to finish without errors");
} }
wasm_utils::pack_instance(raw_module, &mut ctor_module); wasm_utils::pack_instance(raw_module, &mut ctor_module);
parity_wasm::serialize_to_file(&path, ctor_module).expect("Failed to serialize to file"); parity_wasm::serialize_to_file(&path, ctor_module).expect("Failed to serialize to file");

View File

@ -6,6 +6,7 @@ extern crate byteorder;
pub static CREATE_SYMBOL: &'static str = "_create"; pub static CREATE_SYMBOL: &'static str = "_create";
pub static CALL_SYMBOL: &'static str = "_call"; pub static CALL_SYMBOL: &'static str = "_call";
pub static SET_TEMP_RET_SYMBOL: &'static str = "setTempRet0";
pub mod rules; pub mod rules;

View File

@ -1,8 +1,7 @@
use parity_wasm::{serialize,elements, builder, deserialize_buffer}; use parity_wasm::{serialize,elements, builder, deserialize_buffer};
use self::elements::{ External, Section, ResizableLimits, Opcode, DataSegment, InitExpr, Internal }; use self::elements::{ External, Section, ResizableLimits, Opcode, DataSegment, InitExpr, Internal };
use super::CREATE_SYMBOL; use super::{CREATE_SYMBOL, CALL_SYMBOL};
use super::CALL_SYMBOL;
/// If module has an exported "_create" function we want to pack it into "constructor". /// If module has an exported "_create" function we want to pack it into "constructor".
/// `raw_module` is the actual contract code /// `raw_module` is the actual contract code
@ -35,8 +34,10 @@ pub fn pack_instance(raw_module: Vec<u8>, ctor_module: &mut elements::Module) {
// Code data address is an address where we put the contract's code (raw_module) // Code data address is an address where we put the contract's code (raw_module)
let mut code_data_address = 0i32; let mut code_data_address = 0i32;
for section in ctor_module.sections_mut() { for section in ctor_module.sections_mut() {
match section { match section {
// TODO: add data section is there no one
&mut Section::Data(ref mut data_section) => { &mut Section::Data(ref mut data_section) => {
let (index, offset) = if let Some(ref entry) = data_section.entries().iter().last() { let (index, offset) = if let Some(ref entry) = data_section.entries().iter().last() {
if let Opcode::I32Const(offst) = entry.offset().code()[0] { if let Opcode::I32Const(offst) = entry.offset().code()[0] {
@ -89,3 +90,83 @@ pub fn pack_instance(raw_module: Vec<u8>, ctor_module: &mut elements::Module) {
} }
}; };
} }
#[cfg(test)]
mod test {
extern crate parity_wasm;
use parity_wasm::interpreter;
use parity_wasm::ModuleInstanceInterface;
use super::*;
use super::super::optimize;
use super::super::SET_TEMP_RET_SYMBOL;
#[test]
fn call_returns_code() {
let mut module = builder::module()
.import()
.module("env")
.field("memory")
.external()
.memory(1 as u32, Some(1 as u32))
.build()
.data()
.offset(elements::Opcode::I32Const(16))
.value(vec![0u8])
.build()
.function()
.signature().param().i32().build()
.body()
.with_opcodes(elements::Opcodes::new(
vec![
elements::Opcode::End
]
))
.build()
.build()
.function()
.signature().param().i32().build()
.body()
.with_opcodes(elements::Opcodes::new(
vec![
elements::Opcode::End
]
))
.build()
.build()
.export()
.field("_call")
.internal().func(0)
.build()
.export()
.field("_create")
.internal().func(1)
.build()
.build();
let mut ctor_module = module.clone();
optimize(&mut module, vec![CALL_SYMBOL, SET_TEMP_RET_SYMBOL]).expect("Optimizer to finish without errors");
optimize(&mut ctor_module, vec![CREATE_SYMBOL, SET_TEMP_RET_SYMBOL]).expect("Optimizer to finish without errors");
let raw_module = parity_wasm::serialize(module).unwrap();
let raw_module_len = raw_module.len();
pack_instance(raw_module, &mut ctor_module);
let program = parity_wasm::DefaultProgramInstance::new().expect("Program instance to load");
let env_instance = program.module("env").expect("Wasm program to contain env module");
let env_memory = env_instance.memory(interpreter::ItemIndex::Internal(0)).expect("Linear memory to exist in wasm runtime");
let execution_params = interpreter::ExecutionParams::default();
let module = program.add_module("contract", ctor_module, None).expect("Failed to initialize module");
let _ = module.execute_export("_call", execution_params);
let result_code = env_memory.get(20, raw_module_len).expect("Failed to get code");
let result_module: elements::Module = parity_wasm::deserialize_buffer(result_code).expect("Result module is not valid");
let program = parity_wasm::DefaultProgramInstance::new().expect("Program2 instance to load");
let module = program.add_module("contract", result_module, None).expect("Failed to initialize module");
let execution_params = interpreter::ExecutionParams::default();
let _ = module.execute_export("_call", execution_params);
}
}