mirror of
https://github.com/fluencelabs/wasm-utils
synced 2025-06-29 14:31:40 +00:00
data/elements and such
This commit is contained in:
@ -10,7 +10,7 @@ pub fn update_call_index(opcodes: &mut elements::Opcodes, inserted_index: u32) {
|
|||||||
&mut Block(_, ref mut block) | &mut If(_, ref mut block) | &mut Loop(_, ref mut block) => {
|
&mut Block(_, ref mut block) | &mut If(_, ref mut block) | &mut Loop(_, ref mut block) => {
|
||||||
update_call_index(block, inserted_index)
|
update_call_index(block, inserted_index)
|
||||||
},
|
},
|
||||||
&mut Call(ref mut call_index) | &mut CallIndirect(ref mut call_index, _) => {
|
&mut Call(ref mut call_index) => {
|
||||||
if *call_index >= inserted_index { *call_index += 1}
|
if *call_index >= inserted_index { *call_index += 1}
|
||||||
},
|
},
|
||||||
_ => { }
|
_ => { }
|
||||||
|
8
opt/Cargo.lock
generated
8
opt/Cargo.lock
generated
@ -2,7 +2,7 @@
|
|||||||
name = "wasm-opt"
|
name = "wasm-opt"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"parity-wasm 0.3.1 (git+https://github.com/nikvolf/parity-wasm)",
|
"parity-wasm 0.3.2 (git+https://github.com/nikvolf/parity-wasm)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -12,12 +12,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parity-wasm"
|
name = "parity-wasm"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
source = "git+https://github.com/nikvolf/parity-wasm#c52ccb7cd3c54cb0dbf9495dec550b5848737dcb"
|
source = "git+https://github.com/nikvolf/parity-wasm#b11f34f2e5410d0773dcf32699d767d7359e4ca9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
|
"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
|
||||||
"checksum parity-wasm 0.3.1 (git+https://github.com/nikvolf/parity-wasm)" = "<none>"
|
"checksum parity-wasm 0.3.2 (git+https://github.com/nikvolf/parity-wasm)" = "<none>"
|
||||||
|
120
opt/src/main.rs
120
opt/src/main.rs
@ -51,7 +51,7 @@ fn push_code_symbols(module: &elements::Module, opcodes: &[elements::Opcode], de
|
|||||||
|
|
||||||
for opcode in opcodes {
|
for opcode in opcodes {
|
||||||
match opcode {
|
match opcode {
|
||||||
&Call(idx) | &CallIndirect(idx, _) => {
|
&Call(idx) => {
|
||||||
dest.push(resolve_function(module, idx));
|
dest.push(resolve_function(module, idx));
|
||||||
},
|
},
|
||||||
&GetGlobal(idx) | &SetGlobal(idx) => {
|
&GetGlobal(idx) | &SetGlobal(idx) => {
|
||||||
@ -129,30 +129,35 @@ fn expand_symbols(module: &elements::Module, set: &mut HashSet<Symbol>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_call_index(opcodes: &mut elements::Opcodes, eliminated_index: u32) {
|
pub fn update_call_index(opcodes: &mut elements::Opcodes, eliminated_indices: &[usize]) {
|
||||||
use parity_wasm::elements::Opcode::*;
|
use parity_wasm::elements::Opcode::*;
|
||||||
for opcode in opcodes.elements_mut().iter_mut() {
|
for opcode in opcodes.elements_mut().iter_mut() {
|
||||||
match opcode {
|
match opcode {
|
||||||
&mut Block(_, ref mut block) | &mut If(_, ref mut block) | &mut Loop(_, ref mut block) => {
|
&mut Block(_, ref mut block) | &mut If(_, ref mut block) | &mut Loop(_, ref mut block) => {
|
||||||
update_call_index(block, eliminated_index)
|
update_call_index(block, eliminated_indices)
|
||||||
},
|
},
|
||||||
&mut Call(ref mut call_index) | &mut CallIndirect(ref mut call_index, _) => {
|
&mut Call(ref mut call_index) => {
|
||||||
if *call_index > eliminated_index { *call_index -= 1}
|
let totalle = eliminated_indices.iter().take_while(|i| (**i as u32) < *call_index).count();
|
||||||
|
println!("rewired call {} -> call {}", *call_index, *call_index - totalle as u32);
|
||||||
|
*call_index -= totalle as u32;
|
||||||
},
|
},
|
||||||
_ => { },
|
_ => { },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_global_index(opcodes: &mut elements::Opcodes, eliminated_index: u32) {
|
/// Updates global references considering the _ordered_ list of eliminated indices
|
||||||
|
pub fn update_global_index(opcodes: &mut Vec<elements::Opcode>, eliminated_indices: &[usize]) {
|
||||||
use parity_wasm::elements::Opcode::*;
|
use parity_wasm::elements::Opcode::*;
|
||||||
for opcode in opcodes.elements_mut().iter_mut() {
|
for opcode in opcodes.iter_mut() {
|
||||||
match opcode {
|
match opcode {
|
||||||
&mut Block(_, ref mut block) | &mut If(_, ref mut block) | &mut Loop(_, ref mut block) => {
|
&mut Block(_, ref mut block) | &mut If(_, ref mut block) | &mut Loop(_, ref mut block) => {
|
||||||
update_global_index(block, eliminated_index)
|
update_global_index(block.elements_mut(), eliminated_indices)
|
||||||
},
|
},
|
||||||
&mut GetGlobal(ref mut index) | &mut SetGlobal(ref mut index) => {
|
&mut GetGlobal(ref mut index) | &mut SetGlobal(ref mut index) => {
|
||||||
if *index > eliminated_index { *index -= 1}
|
let totalle = eliminated_indices.iter().take_while(|i| (**i as u32) < *index).count();
|
||||||
|
println!("rewired global {} -> global {}", *index, *index - totalle as u32);
|
||||||
|
*index -= totalle as u32;
|
||||||
},
|
},
|
||||||
_ => { },
|
_ => { },
|
||||||
}
|
}
|
||||||
@ -207,6 +212,18 @@ pub fn code_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut elem
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn export_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut elements::ExportSection> {
|
||||||
|
for section in module.sections_mut() {
|
||||||
|
match section {
|
||||||
|
&mut elements::Section::Export(ref mut sect) => {
|
||||||
|
return Some(sect);
|
||||||
|
},
|
||||||
|
_ => { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
||||||
let args = env::args().collect::<Vec<_>>();
|
let args = env::args().collect::<Vec<_>>();
|
||||||
@ -233,6 +250,20 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All symbols used in data/element segments are also should be preserved
|
||||||
|
let mut init_symbols = Vec::new();
|
||||||
|
if let Some(data_section) = module.data_section() {
|
||||||
|
for segment in data_section.entries() {
|
||||||
|
push_code_symbols(&module, segment.offset().code(), &mut init_symbols);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(elements_section) = module.elements_section() {
|
||||||
|
for segment in elements_section.entries() {
|
||||||
|
push_code_symbols(&module, segment.offset().code(), &mut init_symbols);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for symbol in init_symbols.drain(..) { stay.insert(symbol); }
|
||||||
|
|
||||||
// Call function which will traverse the list recursively, filling stay with all symbols
|
// Call function which will traverse the list recursively, filling stay with all symbols
|
||||||
// that are already used by those which already there
|
// that are already used by those which already there
|
||||||
expand_symbols(&mut module, &mut stay);
|
expand_symbols(&mut module, &mut stay);
|
||||||
@ -320,7 +351,7 @@ fn main() {
|
|||||||
index += 1;
|
index += 1;
|
||||||
} else {
|
} else {
|
||||||
functions_section(&mut module).expect("Functons section to exist").entries_mut().remove(index);
|
functions_section(&mut module).expect("Functons section to exist").entries_mut().remove(index);
|
||||||
code_section(&mut module).expect("Functons section to exist").bodies_mut().remove(index);
|
code_section(&mut module).expect("Code section to exist").bodies_mut().remove(index);
|
||||||
|
|
||||||
eliminated_funcs.push(top_funcs + old_index);
|
eliminated_funcs.push(top_funcs + old_index);
|
||||||
println!("Eliminated function({})", top_funcs + old_index);
|
println!("Eliminated function({})", top_funcs + old_index);
|
||||||
@ -328,8 +359,73 @@ fn main() {
|
|||||||
old_index += 1;
|
old_index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, delete all items one by one, updating reference indices in the process
|
// Forth, eliminate unused exports
|
||||||
// (todo: initial naive impementation can be optimized to avoid multiple passes)
|
{
|
||||||
|
let exports = export_section(&mut module).expect("Export section to exist");
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
old_index = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if exports.entries_mut().len() == index { break; }
|
||||||
|
if stay.contains(&Symbol::Export(old_index)) {
|
||||||
|
index += 1;
|
||||||
|
} else {
|
||||||
|
println!("Eliminated export({}, {})", old_index, exports.entries_mut()[index].field());
|
||||||
|
exports.entries_mut().remove(index);
|
||||||
|
}
|
||||||
|
old_index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if eliminated_globals.len() > 0 || eliminated_funcs.len() > 0 {
|
||||||
|
// Finaly, rewire all calls and globals references to the new indices
|
||||||
|
// (only if there is anything to do)
|
||||||
|
eliminated_globals.sort();
|
||||||
|
eliminated_funcs.sort();
|
||||||
|
|
||||||
|
for section in module.sections_mut() {
|
||||||
|
match section {
|
||||||
|
&mut elements::Section::Code(ref mut code_section) => {
|
||||||
|
for ref mut func_body in code_section.bodies_mut() {
|
||||||
|
update_call_index(func_body.code_mut(), &eliminated_funcs);
|
||||||
|
update_global_index(func_body.code_mut().elements_mut(), &eliminated_globals)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&mut elements::Section::Export(ref mut export_section) => {
|
||||||
|
for ref mut export in export_section.entries_mut() {
|
||||||
|
match export.internal_mut() {
|
||||||
|
&mut elements::Internal::Function(ref mut func_index) => {
|
||||||
|
let totalle = eliminated_funcs.iter().take_while(|i| (**i as u32) < *func_index).count();
|
||||||
|
*func_index -= totalle as u32;
|
||||||
|
},
|
||||||
|
&mut elements::Internal::Global(ref mut global_index) => {
|
||||||
|
let totalle = eliminated_globals.iter().take_while(|i| (**i as u32) < *global_index).count();
|
||||||
|
*global_index -= totalle as u32;
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&mut elements::Section::Global(ref mut global_section) => {
|
||||||
|
for ref mut global_entry in global_section.entries_mut() {
|
||||||
|
update_global_index(global_entry.init_expr_mut().code_mut(), &eliminated_globals)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&mut elements::Section::Data(ref mut data_section) => {
|
||||||
|
for ref mut segment in data_section.entries_mut() {
|
||||||
|
update_global_index(segment.offset_mut().code_mut(), &eliminated_globals)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&mut elements::Section::Element(ref mut elements_section) => {
|
||||||
|
for ref mut segment in elements_section.entries_mut() {
|
||||||
|
update_global_index(segment.offset_mut().code_mut(), &eliminated_globals)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
parity_wasm::serialize_to_file(&args[2], module).unwrap();
|
parity_wasm::serialize_to_file(&args[2], module).unwrap();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user