mirror of
https://github.com/pezkuwichain/wasm-instrument.git
synced 2026-06-20 09:01:00 +00:00
Merge pull request #142 from paritytech/at-cleanup
Address all clippy lints
This commit is contained in:
+9
-9
@@ -28,12 +28,12 @@ pub enum Error {
|
|||||||
impl std::fmt::Display for Error {
|
impl std::fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||||
use self::Error::*;
|
use self::Error::*;
|
||||||
match *self {
|
match self {
|
||||||
Io(ref io) => write!(f, "Generic i/o error: {}", io),
|
Io(io) => write!(f, "Generic i/o error: {}", io),
|
||||||
FailedToCopy(ref msg) => write!(f, "{}. Have you tried to run \"cargo build\"?", msg),
|
FailedToCopy(msg) => write!(f, "{}. Have you tried to run \"cargo build\"?", msg),
|
||||||
Decoding(ref err, ref file) => write!(f, "Decoding error ({}). Must be a valid wasm file {}. Pointed wrong file?", err, file),
|
Decoding(err, file) => write!(f, "Decoding error ({}). Must be a valid wasm file {}. Pointed wrong file?", err, file),
|
||||||
Encoding(ref err) => write!(f, "Encoding error ({}). Almost impossible to happen, no free disk space?", err),
|
Encoding(err) => write!(f, "Encoding error ({}). Almost impossible to happen, no free disk space?", err),
|
||||||
Build(ref err) => write!(f, "Build error: {}", err)
|
Build(err) => write!(f, "Build error: {}", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,9 +163,9 @@ fn do_main() -> Result<(), Error> {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let public_api_entries = matches.value_of("public_api")
|
let public_api_entries: Vec<_> = matches.value_of("public_api")
|
||||||
.map(|val| val.split(",").collect())
|
.map(|val| val.split(',').collect())
|
||||||
.unwrap_or(Vec::new());
|
.unwrap_or_default();
|
||||||
|
|
||||||
let target_runtime = match matches.value_of("target-runtime").expect("target-runtime has a default value; qed") {
|
let target_runtime = match matches.value_of("target-runtime").expect("target-runtime has a default value; qed") {
|
||||||
"pwasm" => TargetRuntime::pwasm(),
|
"pwasm" => TargetRuntime::pwasm(),
|
||||||
|
|||||||
+2
-2
@@ -17,8 +17,8 @@ pub struct SourceInput<'a> {
|
|||||||
impl<'a> SourceInput<'a> {
|
impl<'a> SourceInput<'a> {
|
||||||
pub fn new<'b>(target_dir: &'b str, bin_name: &'b str) -> SourceInput<'b> {
|
pub fn new<'b>(target_dir: &'b str, bin_name: &'b str) -> SourceInput<'b> {
|
||||||
SourceInput {
|
SourceInput {
|
||||||
target_dir: target_dir,
|
target_dir,
|
||||||
bin_name: bin_name,
|
bin_name,
|
||||||
final_name: bin_name,
|
final_name: bin_name,
|
||||||
target: SourceTarget::Emscripten,
|
target: SourceTarget::Emscripten,
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -11,7 +11,7 @@ fn fail(msg: &str) -> ! {
|
|||||||
std::process::exit(1)
|
std::process::exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const ALLOWED_IMPORTS: &'static [&'static str] = &[
|
const ALLOWED_IMPORTS: &[&str] = &[
|
||||||
"ret",
|
"ret",
|
||||||
"storage_read",
|
"storage_read",
|
||||||
"storage_write",
|
"storage_write",
|
||||||
@@ -54,14 +54,14 @@ fn main() {
|
|||||||
let module = parity_wasm::deserialize_file(&input).expect("Input module deserialization failed");
|
let module = parity_wasm::deserialize_file(&input).expect("Input module deserialization failed");
|
||||||
|
|
||||||
for section in module.sections() {
|
for section in module.sections() {
|
||||||
match *section {
|
match section {
|
||||||
elements::Section::Import(ref import_section) => {
|
elements::Section::Import(import_section) => {
|
||||||
let mut has_imported_memory_properly_named = false;
|
let mut has_imported_memory_properly_named = false;
|
||||||
for entry in import_section.entries() {
|
for entry in import_section.entries() {
|
||||||
if entry.module() != "env" {
|
if entry.module() != "env" {
|
||||||
fail("All imports should be from env");
|
fail("All imports should be from env");
|
||||||
}
|
}
|
||||||
match *entry.external() {
|
match entry.external() {
|
||||||
elements::External::Function(_) => {
|
elements::External::Function(_) => {
|
||||||
if !ALLOWED_IMPORTS.contains(&entry.field()) {
|
if !ALLOWED_IMPORTS.contains(&entry.field()) {
|
||||||
fail(&format!("'{}' is not supported by the runtime", entry.field()));
|
fail(&format!("'{}' is not supported by the runtime", entry.field()));
|
||||||
|
|||||||
+5
-4
@@ -41,22 +41,23 @@ pub enum SourceTarget {
|
|||||||
impl std::fmt::Display for Error {
|
impl std::fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||||
use self::Error::*;
|
use self::Error::*;
|
||||||
match *self {
|
match self {
|
||||||
Encoding(ref err) => write!(f, "Encoding error ({})", err),
|
Encoding(err) => write!(f, "Encoding error ({})", err),
|
||||||
Optimizer => write!(f, "Optimization error due to missing export section. Pointed wrong file?"),
|
Optimizer => write!(f, "Optimization error due to missing export section. Pointed wrong file?"),
|
||||||
Packing(ref e) => write!(f, "Packing failed due to module structure error: {}. Sure used correct libraries for building contracts?", e),
|
Packing(e) => write!(f, "Packing failed due to module structure error: {}. Sure used correct libraries for building contracts?", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_ctor(module: &elements::Module, target_runtime: &TargetRuntime) -> bool {
|
fn has_ctor(module: &elements::Module, target_runtime: &TargetRuntime) -> bool {
|
||||||
if let Some(ref section) = module.export_section() {
|
if let Some(section) = module.export_section() {
|
||||||
section.entries().iter().any(|e| target_runtime.symbols().create == e.field())
|
section.entries().iter().any(|e| target_runtime.symbols().create == e.field())
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn build(
|
pub fn build(
|
||||||
mut module: elements::Module,
|
mut module: elements::Module,
|
||||||
source_target: SourceTarget,
|
source_target: SourceTarget,
|
||||||
|
|||||||
@@ -22,9 +22,8 @@ pub fn export_mutable_globals(
|
|||||||
module.sections_mut().push(elements::Section::Export(elements::ExportSection::default()));
|
module.sections_mut().push(elements::Section::Export(elements::ExportSection::default()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut symbol_index = 0usize;
|
|
||||||
let prefix: String = prefix.into();
|
let prefix: String = prefix.into();
|
||||||
for export in exports {
|
for (symbol_index, export) in exports.into_iter().enumerate() {
|
||||||
let new_entry = elements::ExportEntry::new(
|
let new_entry = elements::ExportEntry::new(
|
||||||
format!("{}_{}", prefix, symbol_index),
|
format!("{}_{}", prefix, symbol_index),
|
||||||
elements::Internal::Global(
|
elements::Internal::Global(
|
||||||
@@ -35,7 +34,6 @@ pub fn export_mutable_globals(
|
|||||||
.expect("added above if does not exists")
|
.expect("added above if does not exists")
|
||||||
.entries_mut()
|
.entries_mut()
|
||||||
.push(new_entry);
|
.push(new_entry);
|
||||||
symbol_index += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+24
-24
@@ -11,7 +11,7 @@ type Insertion = (usize, u32, u32, String);
|
|||||||
pub fn update_call_index(instructions: &mut elements::Instructions, original_imports: usize, inserts: &[Insertion]) {
|
pub fn update_call_index(instructions: &mut elements::Instructions, original_imports: usize, inserts: &[Insertion]) {
|
||||||
use parity_wasm::elements::Instruction::*;
|
use parity_wasm::elements::Instruction::*;
|
||||||
for instruction in instructions.elements_mut().iter_mut() {
|
for instruction in instructions.elements_mut().iter_mut() {
|
||||||
if let &mut Call(ref mut call_index) = instruction {
|
if let Call(call_index) = instruction {
|
||||||
if let Some(pos) = inserts.iter().position(|x| x.1 == *call_index) {
|
if let Some(pos) = inserts.iter().position(|x| x.1 == *call_index) {
|
||||||
*call_index = (original_imports + pos) as u32;
|
*call_index = (original_imports + pos) as u32;
|
||||||
} else if *call_index as usize > original_imports {
|
} else if *call_index as usize > original_imports {
|
||||||
@@ -21,9 +21,9 @@ pub fn update_call_index(instructions: &mut elements::Instructions, original_imp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn memory_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut elements::MemorySection> {
|
pub fn memory_section(module: &mut elements::Module) -> Option<&mut elements::MemorySection> {
|
||||||
for section in module.sections_mut() {
|
for section in module.sections_mut() {
|
||||||
if let &mut elements::Section::Memory(ref mut sect) = section {
|
if let elements::Section::Memory(sect) = section {
|
||||||
return Some(sect);
|
return Some(sect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,21 +61,21 @@ pub fn externalize_mem(mut module: elements::Module, adjust_pages: Option<u32>,
|
|||||||
fn foreach_public_func_name<F>(mut module: elements::Module, f: F) -> elements::Module
|
fn foreach_public_func_name<F>(mut module: elements::Module, f: F) -> elements::Module
|
||||||
where F: Fn(&mut String)
|
where F: Fn(&mut String)
|
||||||
{
|
{
|
||||||
import_section(&mut module).map(|is| {
|
if let Some(section) = import_section(&mut module) {
|
||||||
for entry in is.entries_mut() {
|
for entry in section.entries_mut() {
|
||||||
if let elements::External::Function(_) = *entry.external() {
|
if let elements::External::Function(_) = *entry.external() {
|
||||||
f(entry.field_mut())
|
f(entry.field_mut())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export_section(&mut module).map(|es| {
|
if let Some(section) = export_section(&mut module) {
|
||||||
for entry in es.entries_mut() {
|
for entry in section.entries_mut() {
|
||||||
if let elements::Internal::Function(_) = *entry.internal() {
|
if let elements::Internal::Function(_) = *entry.internal() {
|
||||||
f(entry.field_mut())
|
f(entry.field_mut())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
module
|
module
|
||||||
}
|
}
|
||||||
@@ -96,13 +96,13 @@ pub fn shrink_unknown_stack(
|
|||||||
let mut new_stack_top = 0;
|
let mut new_stack_top = 0;
|
||||||
for section in module.sections_mut() {
|
for section in module.sections_mut() {
|
||||||
match section {
|
match section {
|
||||||
&mut elements::Section::Data(ref mut data_section) => {
|
elements::Section::Data(data_section) => {
|
||||||
for ref mut data_segment in data_section.entries_mut() {
|
for data_segment in data_section.entries_mut() {
|
||||||
if data_segment
|
if *data_segment
|
||||||
.offset()
|
.offset()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("parity-wasm is compiled without bulk-memory operations")
|
.expect("parity-wasm is compiled without bulk-memory operations")
|
||||||
.code() == &[elements::Instruction::I32Const(4), elements::Instruction::End]
|
.code() == [elements::Instruction::I32Const(4), elements::Instruction::End]
|
||||||
{
|
{
|
||||||
assert_eq!(data_segment.value().len(), 4);
|
assert_eq!(data_segment.value().len(), 4);
|
||||||
let current_val = LittleEndian::read_u32(data_segment.value());
|
let current_val = LittleEndian::read_u32(data_segment.value());
|
||||||
@@ -127,7 +127,7 @@ pub fn externalize(
|
|||||||
.import_section().expect("Import section to exist")
|
.import_section().expect("Import section to exist")
|
||||||
.entries()
|
.entries()
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|e| if let &elements::External::Function(_) = e.external() { true } else { false })
|
.filter(|e| matches!(e.external(), &elements::External::Function(_)))
|
||||||
.count();
|
.count();
|
||||||
|
|
||||||
// First, we find functions indices that are to be rewired to externals
|
// First, we find functions indices that are to be rewired to externals
|
||||||
@@ -141,7 +141,7 @@ pub fn externalize(
|
|||||||
.find(|&(_, entry)| entry.field() == f)
|
.find(|&(_, entry)| entry.field() == f)
|
||||||
.expect("All functions of interest to exist");
|
.expect("All functions of interest to exist");
|
||||||
|
|
||||||
if let &elements::Internal::Function(func_idx) = export.1.internal() {
|
if let elements::Internal::Function(func_idx) = *export.1.internal() {
|
||||||
let type_ref = module
|
let type_ref = module
|
||||||
.function_section().expect("Functions section to exist")
|
.function_section().expect("Functions section to exist")
|
||||||
.entries()[func_idx as usize - import_funcs_total]
|
.entries()[func_idx as usize - import_funcs_total]
|
||||||
@@ -158,12 +158,12 @@ pub fn externalize(
|
|||||||
|
|
||||||
// Second, we duplicate them as import definitions
|
// Second, we duplicate them as import definitions
|
||||||
let mut mbuilder = builder::from_module(module);
|
let mut mbuilder = builder::from_module(module);
|
||||||
for &(_, _, type_ref, ref field) in replaces.iter() {
|
for (_, _, type_ref, field) in replaces.iter() {
|
||||||
mbuilder.push_import(
|
mbuilder.push_import(
|
||||||
builder::import()
|
builder::import()
|
||||||
.module("env")
|
.module("env")
|
||||||
.field(field)
|
.field(field)
|
||||||
.external().func(type_ref)
|
.external().func(*type_ref)
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -174,20 +174,20 @@ pub fn externalize(
|
|||||||
// Third, rewire all calls to imported functions and update all other calls indices
|
// Third, rewire all calls to imported functions and update all other calls indices
|
||||||
for section in module.sections_mut() {
|
for section in module.sections_mut() {
|
||||||
match section {
|
match section {
|
||||||
&mut elements::Section::Code(ref mut code_section) => {
|
elements::Section::Code(code_section) => {
|
||||||
for ref mut func_body in code_section.bodies_mut() {
|
for func_body in code_section.bodies_mut() {
|
||||||
update_call_index(func_body.code_mut(), import_funcs_total, &replaces);
|
update_call_index(func_body.code_mut(), import_funcs_total, &replaces);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&mut elements::Section::Export(ref mut export_section) => {
|
elements::Section::Export(export_section) => {
|
||||||
for ref mut export in export_section.entries_mut() {
|
for export in export_section.entries_mut() {
|
||||||
if let &mut elements::Internal::Function(ref mut func_index) = export.internal_mut() {
|
if let elements::Internal::Function(func_index) = export.internal_mut() {
|
||||||
if *func_index >= import_funcs_total as u32 { *func_index += replaces.len() as u32; }
|
if *func_index >= import_funcs_total as u32 { *func_index += replaces.len() as u32; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&mut elements::Section::Element(ref mut elements_section) => {
|
elements::Section::Element(elements_section) => {
|
||||||
for ref mut segment in elements_section.entries_mut() {
|
for segment in elements_section.entries_mut() {
|
||||||
// update all indirect call addresses initial values
|
// update all indirect call addresses initial values
|
||||||
for func_index in segment.members_mut() {
|
for func_index in segment.members_mut() {
|
||||||
if *func_index >= import_funcs_total as u32 { *func_index += replaces.len() as u32; }
|
if *func_index >= import_funcs_total as u32 { *func_index += replaces.len() as u32; }
|
||||||
|
|||||||
+19
-20
@@ -17,7 +17,7 @@ use rules;
|
|||||||
pub fn update_call_index(instructions: &mut elements::Instructions, inserted_index: u32) {
|
pub fn update_call_index(instructions: &mut elements::Instructions, inserted_index: u32) {
|
||||||
use parity_wasm::elements::Instruction::*;
|
use parity_wasm::elements::Instruction::*;
|
||||||
for instruction in instructions.elements_mut().iter_mut() {
|
for instruction in instructions.elements_mut().iter_mut() {
|
||||||
if let &mut Call(ref mut call_index) = instruction {
|
if let Call(call_index) = instruction {
|
||||||
if *call_index >= inserted_index { *call_index += 1}
|
if *call_index >= inserted_index { *call_index += 1}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -273,7 +273,7 @@ pub(crate) fn determine_metered_blocks(
|
|||||||
for cursor in 0..instructions.elements().len() {
|
for cursor in 0..instructions.elements().len() {
|
||||||
let instruction = &instructions.elements()[cursor];
|
let instruction = &instructions.elements()[cursor];
|
||||||
let instruction_cost = rules.process(instruction)?;
|
let instruction_cost = rules.process(instruction)?;
|
||||||
match *instruction {
|
match instruction {
|
||||||
Block(_) => {
|
Block(_) => {
|
||||||
counter.increment(instruction_cost)?;
|
counter.increment(instruction_cost)?;
|
||||||
|
|
||||||
@@ -303,10 +303,10 @@ pub(crate) fn determine_metered_blocks(
|
|||||||
|
|
||||||
// Label is a relative index into the control stack.
|
// Label is a relative index into the control stack.
|
||||||
let active_index = counter.active_control_block_index().ok_or_else(|| ())?;
|
let active_index = counter.active_control_block_index().ok_or_else(|| ())?;
|
||||||
let target_index = active_index.checked_sub(label as usize).ok_or_else(|| ())?;
|
let target_index = active_index.checked_sub(*label as usize).ok_or_else(|| ())?;
|
||||||
counter.branch(cursor, &[target_index])?;
|
counter.branch(cursor, &[target_index])?;
|
||||||
}
|
}
|
||||||
BrTable(ref br_table_data) => {
|
BrTable(br_table_data) => {
|
||||||
counter.increment(instruction_cost)?;
|
counter.increment(instruction_cost)?;
|
||||||
|
|
||||||
let active_index = counter.active_control_block_index().ok_or_else(|| ())?;
|
let active_index = counter.active_control_block_index().ok_or_else(|| ())?;
|
||||||
@@ -363,7 +363,7 @@ fn insert_metering_calls(
|
|||||||
let mut block_iter = blocks.into_iter().peekable();
|
let mut block_iter = blocks.into_iter().peekable();
|
||||||
for (original_pos, instr) in original_instrs.into_iter().enumerate() {
|
for (original_pos, instr) in original_instrs.into_iter().enumerate() {
|
||||||
// If there the next block starts at this position, inject metering instructions.
|
// If there the next block starts at this position, inject metering instructions.
|
||||||
let used_block = if let Some(ref block) = block_iter.peek() {
|
let used_block = if let Some(block) = block_iter.peek() {
|
||||||
if block.start_pos == original_pos {
|
if block.start_pos == original_pos {
|
||||||
new_instrs.push(I32Const(block.cost as i32));
|
new_instrs.push(I32Const(block.cost as i32));
|
||||||
new_instrs.push(Call(gas_func));
|
new_instrs.push(Call(gas_func));
|
||||||
@@ -453,38 +453,36 @@ pub fn inject_gas_counter(module: elements::Module, rules: &rules::Set, gas_modu
|
|||||||
// Updating calling addresses (all calls to function index >= `gas_func` should be incremented)
|
// Updating calling addresses (all calls to function index >= `gas_func` should be incremented)
|
||||||
for section in module.sections_mut() {
|
for section in module.sections_mut() {
|
||||||
match section {
|
match section {
|
||||||
&mut elements::Section::Code(ref mut code_section) => {
|
elements::Section::Code(code_section) => {
|
||||||
for ref mut func_body in code_section.bodies_mut() {
|
for func_body in code_section.bodies_mut() {
|
||||||
update_call_index(func_body.code_mut(), gas_func);
|
update_call_index(func_body.code_mut(), gas_func);
|
||||||
if let Err(_) = inject_counter(func_body.code_mut(), rules, gas_func) {
|
if inject_counter(func_body.code_mut(), rules, gas_func).is_err() {
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if rules.grow_cost() > 0 {
|
if rules.grow_cost() > 0 && inject_grow_counter(func_body.code_mut(), total_func) > 0 {
|
||||||
if inject_grow_counter(func_body.code_mut(), total_func) > 0 {
|
need_grow_counter = true;
|
||||||
need_grow_counter = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&mut elements::Section::Export(ref mut export_section) => {
|
elements::Section::Export(export_section) => {
|
||||||
for ref mut export in export_section.entries_mut() {
|
for export in export_section.entries_mut() {
|
||||||
if let &mut elements::Internal::Function(ref mut func_index) = export.internal_mut() {
|
if let elements::Internal::Function(func_index) = export.internal_mut() {
|
||||||
if *func_index >= gas_func { *func_index += 1}
|
if *func_index >= gas_func { *func_index += 1}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&mut elements::Section::Element(ref mut elements_section) => {
|
elements::Section::Element(elements_section) => {
|
||||||
// Note that we do not need to check the element type referenced because in the
|
// Note that we do not need to check the element type referenced because in the
|
||||||
// WebAssembly 1.0 spec, the only allowed element type is funcref.
|
// WebAssembly 1.0 spec, the only allowed element type is funcref.
|
||||||
for ref mut segment in elements_section.entries_mut() {
|
for segment in elements_section.entries_mut() {
|
||||||
// update all indirect call addresses initial values
|
// update all indirect call addresses initial values
|
||||||
for func_index in segment.members_mut() {
|
for func_index in segment.members_mut() {
|
||||||
if *func_index >= gas_func { *func_index += 1}
|
if *func_index >= gas_func { *func_index += 1}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&mut elements::Section::Start(ref mut start_idx) => {
|
elements::Section::Start(start_idx) => {
|
||||||
if *start_idx >= gas_func { *start_idx += 1}
|
if *start_idx >= gas_func { *start_idx += 1}
|
||||||
},
|
},
|
||||||
_ => { }
|
_ => { }
|
||||||
@@ -685,9 +683,10 @@ mod tests {
|
|||||||
|
|
||||||
let rules = rules::Set::default().with_forbidden_floats();
|
let rules = rules::Set::default().with_forbidden_floats();
|
||||||
|
|
||||||
if let Err(_) = inject_gas_counter(module, &rules, "env") { }
|
|
||||||
else { panic!("Should be error because of the forbidden operation")}
|
|
||||||
|
|
||||||
|
if inject_gas_counter(module, &rules, "env").is_ok() {
|
||||||
|
panic!("Should be error because of the forbidden operation")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_wat(source: &str) -> elements::Module {
|
fn parse_wat(source: &str) -> elements::Module {
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ fn build_control_flow_graph(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let instruction_cost = rules.process(instruction)?;
|
let instruction_cost = rules.process(instruction)?;
|
||||||
match *instruction {
|
match instruction {
|
||||||
Instruction::Block(_) => {
|
Instruction::Block(_) => {
|
||||||
graph.increment_actual_cost(active_node_id, instruction_cost);
|
graph.increment_actual_cost(active_node_id, instruction_cost);
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ fn build_control_flow_graph(
|
|||||||
graph.increment_actual_cost(active_node_id, instruction_cost);
|
graph.increment_actual_cost(active_node_id, instruction_cost);
|
||||||
|
|
||||||
let active_frame_idx = stack.len() - 1;
|
let active_frame_idx = stack.len() - 1;
|
||||||
let target_frame_idx = active_frame_idx - (label as usize);
|
let target_frame_idx = active_frame_idx - (*label as usize);
|
||||||
graph.new_edge(active_node_id, &stack[target_frame_idx]);
|
graph.new_edge(active_node_id, &stack[target_frame_idx]);
|
||||||
|
|
||||||
// Next instruction is unreachable, but carry on anyway.
|
// Next instruction is unreachable, but carry on anyway.
|
||||||
@@ -233,7 +233,7 @@ fn build_control_flow_graph(
|
|||||||
graph.increment_actual_cost(active_node_id, instruction_cost);
|
graph.increment_actual_cost(active_node_id, instruction_cost);
|
||||||
|
|
||||||
let active_frame_idx = stack.len() - 1;
|
let active_frame_idx = stack.len() - 1;
|
||||||
let target_frame_idx = active_frame_idx - (label as usize);
|
let target_frame_idx = active_frame_idx - (*label as usize);
|
||||||
graph.new_edge(active_node_id, &stack[target_frame_idx]);
|
graph.new_edge(active_node_id, &stack[target_frame_idx]);
|
||||||
|
|
||||||
let new_node_id = graph.add_node();
|
let new_node_id = graph.add_node();
|
||||||
@@ -241,7 +241,7 @@ fn build_control_flow_graph(
|
|||||||
graph.new_forward_edge(active_node_id, new_node_id);
|
graph.new_forward_edge(active_node_id, new_node_id);
|
||||||
graph.set_first_instr_pos(new_node_id, cursor + 1);
|
graph.set_first_instr_pos(new_node_id, cursor + 1);
|
||||||
}
|
}
|
||||||
Instruction::BrTable(ref br_table_data) => {
|
Instruction::BrTable(br_table_data) => {
|
||||||
graph.increment_actual_cost(active_node_id, instruction_cost);
|
graph.increment_actual_cost(active_node_id, instruction_cost);
|
||||||
|
|
||||||
let active_frame_idx = stack.len() - 1;
|
let active_frame_idx = stack.len() - 1;
|
||||||
@@ -303,7 +303,7 @@ fn validate_graph_gas_costs(graph: &ControlFlowGraph) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for loop_node_id in node.loopback_edges.iter() {
|
for loop_node_id in node.loopback_edges.iter() {
|
||||||
let (ref mut loop_actual, ref mut loop_charged) = loop_costs.get_mut(loop_node_id)
|
let (loop_actual, loop_charged) = loop_costs.get_mut(loop_node_id)
|
||||||
.expect("cannot arrive at loopback edge without visiting loop entry node");
|
.expect("cannot arrive at loopback edge without visiting loop entry node");
|
||||||
if loop_actual != loop_charged {
|
if loop_actual != loop_charged {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
+62
-72
@@ -238,12 +238,10 @@ impl Module {
|
|||||||
/// Initialize module from parity-wasm `Module`.
|
/// Initialize module from parity-wasm `Module`.
|
||||||
pub fn from_elements(module: &elements::Module) -> Result<Self, Error> {
|
pub fn from_elements(module: &elements::Module) -> Result<Self, Error> {
|
||||||
|
|
||||||
let mut idx = 0;
|
|
||||||
let mut res = Module::default();
|
let mut res = Module::default();
|
||||||
|
|
||||||
let mut imported_functions = 0;
|
let mut imported_functions = 0;
|
||||||
|
|
||||||
for section in module.sections() {
|
for (idx, section) in module.sections().iter().enumerate() {
|
||||||
match section {
|
match section {
|
||||||
elements::Section::Type(type_section) => {
|
elements::Section::Type(type_section) => {
|
||||||
res.types = RefList::from_slice(type_section.types());
|
res.types = RefList::from_slice(type_section.types());
|
||||||
@@ -260,7 +258,7 @@ impl Module {
|
|||||||
},
|
},
|
||||||
elements::External::Memory(m) => {
|
elements::External::Memory(m) => {
|
||||||
res.memory.push(Memory {
|
res.memory.push(Memory {
|
||||||
limits: m.limits().clone(),
|
limits: *m.limits(),
|
||||||
origin: entry.into(),
|
origin: entry.into(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -273,7 +271,7 @@ impl Module {
|
|||||||
},
|
},
|
||||||
elements::External::Table(t) => {
|
elements::External::Table(t) => {
|
||||||
res.tables.push(Table {
|
res.tables.push(Table {
|
||||||
limits: t.limits().clone(),
|
limits: *t.limits(),
|
||||||
origin: entry.into(),
|
origin: entry.into(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -296,7 +294,7 @@ impl Module {
|
|||||||
elements::Section::Table(table_section) => {
|
elements::Section::Table(table_section) => {
|
||||||
for t in table_section.entries() {
|
for t in table_section.entries() {
|
||||||
res.tables.push(Table {
|
res.tables.push(Table {
|
||||||
limits: t.limits().clone(),
|
limits: *t.limits(),
|
||||||
origin: ImportedOrDeclared::Declared(()),
|
origin: ImportedOrDeclared::Declared(()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -304,7 +302,7 @@ impl Module {
|
|||||||
elements::Section::Memory(table_section) => {
|
elements::Section::Memory(table_section) => {
|
||||||
for t in table_section.entries() {
|
for t in table_section.entries() {
|
||||||
res.memory.push(Memory {
|
res.memory.push(Memory {
|
||||||
limits: t.limits().clone(),
|
limits: *t.limits(),
|
||||||
origin: ImportedOrDeclared::Declared(()),
|
origin: ImportedOrDeclared::Declared(()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -322,21 +320,21 @@ impl Module {
|
|||||||
elements::Section::Export(export_section) => {
|
elements::Section::Export(export_section) => {
|
||||||
for e in export_section.entries() {
|
for e in export_section.entries() {
|
||||||
let local = match e.internal() {
|
let local = match e.internal() {
|
||||||
&elements::Internal::Function(func_idx) => {
|
elements::Internal::Function(func_idx) => {
|
||||||
ExportLocal::Func(res.funcs.clone_ref(func_idx as usize))
|
ExportLocal::Func(res.funcs.clone_ref(*func_idx as usize))
|
||||||
},
|
},
|
||||||
&elements::Internal::Global(global_idx) => {
|
elements::Internal::Global(global_idx) => {
|
||||||
ExportLocal::Global(res.globals.clone_ref(global_idx as usize))
|
ExportLocal::Global(res.globals.clone_ref(*global_idx as usize))
|
||||||
},
|
},
|
||||||
&elements::Internal::Memory(mem_idx) => {
|
elements::Internal::Memory(mem_idx) => {
|
||||||
ExportLocal::Memory(res.memory.clone_ref(mem_idx as usize))
|
ExportLocal::Memory(res.memory.clone_ref(*mem_idx as usize))
|
||||||
},
|
},
|
||||||
&elements::Internal::Table(table_idx) => {
|
elements::Internal::Table(table_idx) => {
|
||||||
ExportLocal::Table(res.tables.clone_ref(table_idx as usize))
|
ExportLocal::Table(res.tables.clone_ref(*table_idx as usize))
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
res.exports.push(Export { local: local, name: e.field().to_owned() })
|
res.exports.push(Export { local, name: e.field().to_owned() })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
elements::Section::Start(start_func) => {
|
elements::Section::Start(start_func) => {
|
||||||
@@ -368,25 +366,21 @@ impl Module {
|
|||||||
|
|
||||||
res.elements.push(ElementSegment {
|
res.elements.push(ElementSegment {
|
||||||
value: funcs_map,
|
value: funcs_map,
|
||||||
location: location,
|
location,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
elements::Section::Code(code_section) => {
|
elements::Section::Code(code_section) => {
|
||||||
let mut idx = 0;
|
for (idx, func_body) in code_section.bodies().iter().enumerate() {
|
||||||
for func_body in code_section.bodies() {
|
|
||||||
let code = res.map_instructions(func_body.code().elements());
|
let code = res.map_instructions(func_body.code().elements());
|
||||||
|
|
||||||
let mut func = res.funcs.get_ref(imported_functions + idx).write();
|
let mut func = res.funcs.get_ref(imported_functions + idx).write();
|
||||||
match func.origin {
|
match &mut func.origin {
|
||||||
ImportedOrDeclared::Declared(ref mut body) => {
|
ImportedOrDeclared::Declared(body) => {
|
||||||
body.code = code;
|
body.code = code;
|
||||||
body.locals = func_body.locals().iter().cloned().collect();
|
body.locals = func_body.locals().to_vec();
|
||||||
},
|
},
|
||||||
_ => { return Err(Error::InconsistentSource); }
|
_ => { return Err(Error::InconsistentSource); }
|
||||||
}
|
}
|
||||||
|
|
||||||
idx += 1;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
elements::Section::Data(data_section) => {
|
elements::Section::Data(data_section) => {
|
||||||
@@ -402,7 +396,7 @@ impl Module {
|
|||||||
|
|
||||||
res.data.push(DataSegment {
|
res.data.push(DataSegment {
|
||||||
value: data_segment.value().to_vec(),
|
value: data_segment.value().to_vec(),
|
||||||
location: location,
|
location,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -410,7 +404,6 @@ impl Module {
|
|||||||
res.other.insert(idx, section.clone());
|
res.other.insert(idx, section.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
idx += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
@@ -425,7 +418,7 @@ impl Module {
|
|||||||
|
|
||||||
custom_round(&self.other, &mut idx, &mut sections);
|
custom_round(&self.other, &mut idx, &mut sections);
|
||||||
|
|
||||||
if self.types.len() > 0 {
|
if !self.types.is_empty() {
|
||||||
// TYPE SECTION (1)
|
// TYPE SECTION (1)
|
||||||
let mut type_section = elements::TypeSection::default();
|
let mut type_section = elements::TypeSection::default();
|
||||||
{
|
{
|
||||||
@@ -447,8 +440,8 @@ impl Module {
|
|||||||
let add = {
|
let add = {
|
||||||
let imports = import_section.entries_mut();
|
let imports = import_section.entries_mut();
|
||||||
for func in self.funcs.iter() {
|
for func in self.funcs.iter() {
|
||||||
match func.read().origin {
|
match &func.read().origin {
|
||||||
Imported(ref module, ref field) => {
|
Imported(module, field) => {
|
||||||
imports.push(
|
imports.push(
|
||||||
elements::ImportEntry::new(
|
elements::ImportEntry::new(
|
||||||
module.to_owned(),
|
module.to_owned(),
|
||||||
@@ -464,8 +457,8 @@ impl Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for global in self.globals.iter() {
|
for global in self.globals.iter() {
|
||||||
match global.read().origin {
|
match &global.read().origin {
|
||||||
Imported(ref module, ref field) => {
|
Imported(module, field) => {
|
||||||
imports.push(
|
imports.push(
|
||||||
elements::ImportEntry::new(
|
elements::ImportEntry::new(
|
||||||
module.to_owned(),
|
module.to_owned(),
|
||||||
@@ -484,8 +477,8 @@ impl Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for memory in self.memory.iter() {
|
for memory in self.memory.iter() {
|
||||||
match memory.read().origin {
|
match &memory.read().origin {
|
||||||
Imported(ref module, ref field) => {
|
Imported(module, field) => {
|
||||||
imports.push(
|
imports.push(
|
||||||
elements::ImportEntry::new(
|
elements::ImportEntry::new(
|
||||||
module.to_owned(),
|
module.to_owned(),
|
||||||
@@ -504,8 +497,8 @@ impl Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for table in self.tables.iter() {
|
for table in self.tables.iter() {
|
||||||
match table.read().origin {
|
match &table.read().origin {
|
||||||
Imported(ref module, ref field) => {
|
Imported(module, field) => {
|
||||||
imports.push(
|
imports.push(
|
||||||
elements::ImportEntry::new(
|
elements::ImportEntry::new(
|
||||||
module.to_owned(),
|
module.to_owned(),
|
||||||
@@ -522,7 +515,7 @@ impl Module {
|
|||||||
_ => continue,
|
_ => continue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
imports.len() > 0
|
!imports.is_empty()
|
||||||
};
|
};
|
||||||
|
|
||||||
if add {
|
if add {
|
||||||
@@ -531,7 +524,7 @@ impl Module {
|
|||||||
custom_round(&self.other, &mut idx, &mut sections);
|
custom_round(&self.other, &mut idx, &mut sections);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.funcs.len() > 0 {
|
if !self.funcs.is_empty() {
|
||||||
// FUNC SECTION (3)
|
// FUNC SECTION (3)
|
||||||
let mut func_section = elements::FunctionSection::default();
|
let mut func_section = elements::FunctionSection::default();
|
||||||
{
|
{
|
||||||
@@ -554,7 +547,7 @@ impl Module {
|
|||||||
custom_round(&self.other, &mut idx, &mut sections);
|
custom_round(&self.other, &mut idx, &mut sections);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.tables.len() > 0 {
|
if !self.tables.is_empty() {
|
||||||
// TABLE SECTION (4)
|
// TABLE SECTION (4)
|
||||||
let mut table_section = elements::TableSection::default();
|
let mut table_section = elements::TableSection::default();
|
||||||
{
|
{
|
||||||
@@ -578,7 +571,7 @@ impl Module {
|
|||||||
custom_round(&self.other, &mut idx, &mut sections);
|
custom_round(&self.other, &mut idx, &mut sections);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.memory.len() > 0 {
|
if !self.memory.is_empty() {
|
||||||
// MEMORY SECTION (5)
|
// MEMORY SECTION (5)
|
||||||
let mut memory_section = elements::MemorySection::default();
|
let mut memory_section = elements::MemorySection::default();
|
||||||
{
|
{
|
||||||
@@ -602,15 +595,15 @@ impl Module {
|
|||||||
custom_round(&self.other, &mut idx, &mut sections);
|
custom_round(&self.other, &mut idx, &mut sections);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.globals.len() > 0 {
|
if !self.globals.is_empty() {
|
||||||
// GLOBAL SECTION (6)
|
// GLOBAL SECTION (6)
|
||||||
let mut global_section = elements::GlobalSection::default();
|
let mut global_section = elements::GlobalSection::default();
|
||||||
{
|
{
|
||||||
let globals = global_section.entries_mut();
|
let globals = global_section.entries_mut();
|
||||||
|
|
||||||
for global in self.globals.iter() {
|
for global in self.globals.iter() {
|
||||||
match global.read().origin {
|
match &global.read().origin {
|
||||||
Declared(ref init_code) => {
|
Declared(init_code) => {
|
||||||
globals.push(elements::GlobalEntry::new(
|
globals.push(elements::GlobalEntry::new(
|
||||||
elements::GlobalType::new(global.read().content, global.read().is_mut),
|
elements::GlobalType::new(global.read().content, global.read().is_mut),
|
||||||
elements::InitExpr::new(self.generate_instructions(&init_code[..])),
|
elements::InitExpr::new(self.generate_instructions(&init_code[..])),
|
||||||
@@ -626,24 +619,24 @@ impl Module {
|
|||||||
custom_round(&self.other, &mut idx, &mut sections);
|
custom_round(&self.other, &mut idx, &mut sections);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.exports.len() > 0 {
|
if !self.exports.is_empty() {
|
||||||
// EXPORT SECTION (7)
|
// EXPORT SECTION (7)
|
||||||
let mut export_section = elements::ExportSection::default();
|
let mut export_section = elements::ExportSection::default();
|
||||||
{
|
{
|
||||||
let exports = export_section.entries_mut();
|
let exports = export_section.entries_mut();
|
||||||
|
|
||||||
for export in self.exports.iter() {
|
for export in self.exports.iter() {
|
||||||
let internal = match export.local {
|
let internal = match &export.local {
|
||||||
ExportLocal::Func(ref func_ref) => {
|
ExportLocal::Func(func_ref) => {
|
||||||
elements::Internal::Function(func_ref.order().ok_or(Error::DetachedEntry)? as u32)
|
elements::Internal::Function(func_ref.order().ok_or(Error::DetachedEntry)? as u32)
|
||||||
},
|
},
|
||||||
ExportLocal::Global(ref global_ref) => {
|
ExportLocal::Global(global_ref) => {
|
||||||
elements::Internal::Global(global_ref.order().ok_or(Error::DetachedEntry)? as u32)
|
elements::Internal::Global(global_ref.order().ok_or(Error::DetachedEntry)? as u32)
|
||||||
},
|
},
|
||||||
ExportLocal::Table(ref table_ref) => {
|
ExportLocal::Table(table_ref) => {
|
||||||
elements::Internal::Table(table_ref.order().ok_or(Error::DetachedEntry)? as u32)
|
elements::Internal::Table(table_ref.order().ok_or(Error::DetachedEntry)? as u32)
|
||||||
},
|
},
|
||||||
ExportLocal::Memory(ref memory_ref) => {
|
ExportLocal::Memory(memory_ref) => {
|
||||||
elements::Internal::Memory(memory_ref.order().ok_or(Error::DetachedEntry)? as u32)
|
elements::Internal::Memory(memory_ref.order().ok_or(Error::DetachedEntry)? as u32)
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -657,22 +650,22 @@ impl Module {
|
|||||||
custom_round(&self.other, &mut idx, &mut sections);
|
custom_round(&self.other, &mut idx, &mut sections);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref func_ref) = self.start {
|
if let Some(func_ref) = &self.start {
|
||||||
// START SECTION (8)
|
// START SECTION (8)
|
||||||
sections.push(elements::Section::Start(
|
sections.push(elements::Section::Start(
|
||||||
func_ref.order().ok_or(Error::DetachedEntry)? as u32
|
func_ref.order().ok_or(Error::DetachedEntry)? as u32
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.elements.len() > 0 {
|
if !self.elements.is_empty() {
|
||||||
// START SECTION (9)
|
// START SECTION (9)
|
||||||
let mut element_section = elements::ElementSection::default();
|
let mut element_section = elements::ElementSection::default();
|
||||||
{
|
{
|
||||||
let element_segments = element_section.entries_mut();
|
let element_segments = element_section.entries_mut();
|
||||||
|
|
||||||
for element in self.elements.iter() {
|
for element in self.elements.iter() {
|
||||||
match element.location {
|
match &element.location {
|
||||||
SegmentLocation::Default(ref offset_expr) => {
|
SegmentLocation::Default(offset_expr) => {
|
||||||
let mut elements_map = Vec::new();
|
let mut elements_map = Vec::new();
|
||||||
for f in element.value.iter() {
|
for f in element.value.iter() {
|
||||||
elements_map.push(f.order().ok_or(Error::DetachedEntry)? as u32);
|
elements_map.push(f.order().ok_or(Error::DetachedEntry)? as u32);
|
||||||
@@ -697,15 +690,15 @@ impl Module {
|
|||||||
custom_round(&self.other, &mut idx, &mut sections);
|
custom_round(&self.other, &mut idx, &mut sections);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.funcs.len() > 0 {
|
if !self.funcs.is_empty() {
|
||||||
// CODE SECTION (10)
|
// CODE SECTION (10)
|
||||||
let mut code_section = elements::CodeSection::default();
|
let mut code_section = elements::CodeSection::default();
|
||||||
{
|
{
|
||||||
let funcs = code_section.bodies_mut();
|
let funcs = code_section.bodies_mut();
|
||||||
|
|
||||||
for func in self.funcs.iter() {
|
for func in self.funcs.iter() {
|
||||||
match func.read().origin {
|
match &func.read().origin {
|
||||||
Declared(ref body) => {
|
Declared(body) => {
|
||||||
funcs.push(elements::FuncBody::new(
|
funcs.push(elements::FuncBody::new(
|
||||||
body.locals.clone(),
|
body.locals.clone(),
|
||||||
elements::Instructions::new(self.generate_instructions(&body.code[..])),
|
elements::Instructions::new(self.generate_instructions(&body.code[..])),
|
||||||
@@ -722,15 +715,15 @@ impl Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if self.data.len() > 0 {
|
if !self.data.is_empty() {
|
||||||
// DATA SECTION (11)
|
// DATA SECTION (11)
|
||||||
let mut data_section = elements::DataSection::default();
|
let mut data_section = elements::DataSection::default();
|
||||||
{
|
{
|
||||||
let data_segments = data_section.entries_mut();
|
let data_segments = data_section.entries_mut();
|
||||||
|
|
||||||
for data_entry in self.data.iter() {
|
for data_entry in self.data.iter() {
|
||||||
match data_entry.location {
|
match &data_entry.location {
|
||||||
SegmentLocation::Default(ref offset_expr) => {
|
SegmentLocation::Default(offset_expr) => {
|
||||||
data_segments.push(
|
data_segments.push(
|
||||||
elements::DataSegment::new(
|
elements::DataSegment::new(
|
||||||
0,
|
0,
|
||||||
@@ -843,7 +836,7 @@ mod tests {
|
|||||||
let element_func = &sample.elements[0].value[1];
|
let element_func = &sample.elements[0].value[1];
|
||||||
let rfunc = element_func.read();
|
let rfunc = element_func.read();
|
||||||
let rtype = &**rfunc.type_ref.read();
|
let rtype = &**rfunc.type_ref.read();
|
||||||
let elements::Type::Function(ref ftype) = rtype;
|
let elements::Type::Function(ftype) = rtype;
|
||||||
|
|
||||||
// it's func#1 in the function space
|
// it's func#1 in the function space
|
||||||
assert_eq!(rfunc.order(), Some(1));
|
assert_eq!(rfunc.order(), Some(1));
|
||||||
@@ -857,7 +850,7 @@ mod tests {
|
|||||||
let element_func = &sample.elements[0].value[1];
|
let element_func = &sample.elements[0].value[1];
|
||||||
let rfunc = element_func.read();
|
let rfunc = element_func.read();
|
||||||
let rtype = &**rfunc.type_ref.read();
|
let rtype = &**rfunc.type_ref.read();
|
||||||
let elements::Type::Function(ref ftype) = rtype;
|
let elements::Type::Function(ftype) = rtype;
|
||||||
|
|
||||||
// import deleted so now it's func #0
|
// import deleted so now it's func #0
|
||||||
assert_eq!(rfunc.order(), Some(0));
|
assert_eq!(rfunc.order(), Some(0));
|
||||||
@@ -891,10 +884,7 @@ mod tests {
|
|||||||
let declared_func_2 = sample.funcs.clone_ref(2);
|
let declared_func_2 = sample.funcs.clone_ref(2);
|
||||||
|
|
||||||
let mut tx = sample.funcs.begin_insert_not_until(
|
let mut tx = sample.funcs.begin_insert_not_until(
|
||||||
|f| match f.origin {
|
|f| matches!(f.origin, super::ImportedOrDeclared::Imported(_, _))
|
||||||
super::ImportedOrDeclared::Imported(_, _) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let new_import_func = tx.push(super::Func {
|
let new_import_func = tx.push(super::Func {
|
||||||
@@ -908,9 +898,9 @@ mod tests {
|
|||||||
assert_eq!(declared_func_2.order(), Some(3));
|
assert_eq!(declared_func_2.order(), Some(3));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
match &declared_func_2.read().origin {
|
match &declared_func_2.read().origin {
|
||||||
super::ImportedOrDeclared::Declared(ref body) => {
|
super::ImportedOrDeclared::Declared(body) => {
|
||||||
match body.code[1] {
|
match &body.code[1] {
|
||||||
super::Instruction::Call(ref called_func) => called_func.order(),
|
super::Instruction::Call(called_func) => called_func.order(),
|
||||||
_ => panic!("instruction #2 should be a call!"),
|
_ => panic!("instruction #2 should be a call!"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -975,10 +965,10 @@ mod tests {
|
|||||||
let declared_func_2 = sample.funcs.clone_ref(2);
|
let declared_func_2 = sample.funcs.clone_ref(2);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
match &declared_func_2.read().origin {
|
match &declared_func_2.read().origin {
|
||||||
super::ImportedOrDeclared::Declared(ref body) => {
|
super::ImportedOrDeclared::Declared(body) => {
|
||||||
match body.code[0] {
|
match &body.code[0] {
|
||||||
super::Instruction::Call(ref called_func) => called_func.order(),
|
super::Instruction::Call(called_func) => called_func.order(),
|
||||||
ref wrong_instruction => panic!("instruction #2 should be a call but got {:?}!", wrong_instruction),
|
wrong_instruction => panic!("instruction #2 should be a call but got {:?}!", wrong_instruction),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => panic!("func #0 should be declared!"),
|
_ => panic!("func #0 should be declared!"),
|
||||||
|
|||||||
+50
-49
@@ -25,7 +25,7 @@ pub fn optimize(
|
|||||||
// which in turn compile in unused imports and leaves unused functions
|
// which in turn compile in unused imports and leaves unused functions
|
||||||
|
|
||||||
// try to parse name section
|
// try to parse name section
|
||||||
let module_temp = mem::replace(module, elements::Module::default());
|
let module_temp = mem::take(module);
|
||||||
let module_temp = module_temp
|
let module_temp = module_temp
|
||||||
.parse_names()
|
.parse_names()
|
||||||
.unwrap_or_else(|(_err, module)| module);
|
.unwrap_or_else(|(_err, module)| module);
|
||||||
@@ -34,7 +34,7 @@ pub fn optimize(
|
|||||||
// Algo starts from the top, listing all items that should stay
|
// Algo starts from the top, listing all items that should stay
|
||||||
let mut stay = Set::new();
|
let mut stay = Set::new();
|
||||||
for (index, entry) in module.export_section().ok_or(Error::NoExportSection)?.entries().iter().enumerate() {
|
for (index, entry) in module.export_section().ok_or(Error::NoExportSection)?.entries().iter().enumerate() {
|
||||||
if used_exports.iter().find(|e| **e == entry.field()).is_some() {
|
if used_exports.iter().any(|e| *e == entry.field()) {
|
||||||
stay.insert(Symbol::Export(index));
|
stay.insert(Symbol::Export(index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ pub fn optimize(
|
|||||||
loop {
|
loop {
|
||||||
let mut remove = false;
|
let mut remove = false;
|
||||||
match imports.entries()[index].external() {
|
match imports.entries()[index].external() {
|
||||||
&elements::External::Function(_) => {
|
elements::External::Function(_) => {
|
||||||
if stay.contains(&Symbol::Import(old_index)) {
|
if stay.contains(&Symbol::Import(old_index)) {
|
||||||
index += 1;
|
index += 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -129,7 +129,7 @@ pub fn optimize(
|
|||||||
}
|
}
|
||||||
top_funcs += 1;
|
top_funcs += 1;
|
||||||
},
|
},
|
||||||
&elements::External::Global(_) => {
|
elements::External::Global(_) => {
|
||||||
if stay.contains(&Symbol::Import(old_index)) {
|
if stay.contains(&Symbol::Import(old_index)) {
|
||||||
index += 1;
|
index += 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -210,54 +210,55 @@ pub fn optimize(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if eliminated_globals.len() > 0 || eliminated_funcs.len() > 0 || eliminated_types.len() > 0 {
|
if !eliminated_globals.is_empty() || !eliminated_funcs.is_empty() || !eliminated_types.is_empty() {
|
||||||
// Finaly, rewire all calls, globals references and types to the new indices
|
// Finaly, rewire all calls, globals references and types to the new indices
|
||||||
// (only if there is anything to do)
|
// (only if there is anything to do)
|
||||||
eliminated_globals.sort();
|
// When sorting primitives sorting unstable is faster without any difference in result.
|
||||||
eliminated_funcs.sort();
|
eliminated_globals.sort_unstable();
|
||||||
eliminated_types.sort();
|
eliminated_funcs.sort_unstable();
|
||||||
|
eliminated_types.sort_unstable();
|
||||||
|
|
||||||
for section in module.sections_mut() {
|
for section in module.sections_mut() {
|
||||||
match section {
|
match section {
|
||||||
&mut elements::Section::Start(ref mut func_index) if eliminated_funcs.len() > 0 => {
|
elements::Section::Start(func_index) if !eliminated_funcs.is_empty() => {
|
||||||
let totalle = eliminated_funcs.iter().take_while(|i| (**i as u32) < *func_index).count();
|
let totalle = eliminated_funcs.iter().take_while(|i| (**i as u32) < *func_index).count();
|
||||||
*func_index -= totalle as u32;
|
*func_index -= totalle as u32;
|
||||||
},
|
},
|
||||||
&mut elements::Section::Function(ref mut function_section) if eliminated_types.len() > 0 => {
|
elements::Section::Function(function_section) if !eliminated_types.is_empty() => {
|
||||||
for ref mut func_signature in function_section.entries_mut() {
|
for func_signature in function_section.entries_mut() {
|
||||||
let totalle = eliminated_types.iter().take_while(|i| (**i as u32) < func_signature.type_ref()).count();
|
let totalle = eliminated_types.iter().take_while(|i| (**i as u32) < func_signature.type_ref()).count();
|
||||||
*func_signature.type_ref_mut() -= totalle as u32;
|
*func_signature.type_ref_mut() -= totalle as u32;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&mut elements::Section::Import(ref mut import_section) if eliminated_types.len() > 0 => {
|
elements::Section::Import(import_section) if !eliminated_types.is_empty() => {
|
||||||
for ref mut import_entry in import_section.entries_mut() {
|
for import_entry in import_section.entries_mut() {
|
||||||
if let &mut elements::External::Function(ref mut type_ref) = import_entry.external_mut() {
|
if let elements::External::Function(type_ref) = import_entry.external_mut() {
|
||||||
let totalle = eliminated_types.iter().take_while(|i| (**i as u32) < *type_ref).count();
|
let totalle = eliminated_types.iter().take_while(|i| (**i as u32) < *type_ref).count();
|
||||||
*type_ref -= totalle as u32;
|
*type_ref -= totalle as u32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&mut elements::Section::Code(ref mut code_section) if eliminated_globals.len() > 0 || eliminated_funcs.len() > 0 => {
|
elements::Section::Code(code_section) if !eliminated_globals.is_empty() || !eliminated_funcs.is_empty() => {
|
||||||
for ref mut func_body in code_section.bodies_mut() {
|
for func_body in code_section.bodies_mut() {
|
||||||
if eliminated_funcs.len() > 0 {
|
if !eliminated_funcs.is_empty() {
|
||||||
update_call_index(func_body.code_mut(), &eliminated_funcs);
|
update_call_index(func_body.code_mut(), &eliminated_funcs);
|
||||||
}
|
}
|
||||||
if eliminated_globals.len() > 0 {
|
if !eliminated_globals.is_empty() {
|
||||||
update_global_index(func_body.code_mut().elements_mut(), &eliminated_globals)
|
update_global_index(func_body.code_mut().elements_mut(), &eliminated_globals)
|
||||||
}
|
}
|
||||||
if eliminated_types.len() > 0 {
|
if !eliminated_types.is_empty() {
|
||||||
update_type_index(func_body.code_mut(), &eliminated_types)
|
update_type_index(func_body.code_mut(), &eliminated_types)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&mut elements::Section::Export(ref mut export_section) => {
|
elements::Section::Export(export_section) => {
|
||||||
for ref mut export in export_section.entries_mut() {
|
for export in export_section.entries_mut() {
|
||||||
match export.internal_mut() {
|
match export.internal_mut() {
|
||||||
&mut elements::Internal::Function(ref mut func_index) => {
|
elements::Internal::Function(func_index) => {
|
||||||
let totalle = eliminated_funcs.iter().take_while(|i| (**i as u32) < *func_index).count();
|
let totalle = eliminated_funcs.iter().take_while(|i| (**i as u32) < *func_index).count();
|
||||||
*func_index -= totalle as u32;
|
*func_index -= totalle as u32;
|
||||||
},
|
},
|
||||||
&mut elements::Internal::Global(ref mut global_index) => {
|
elements::Internal::Global(global_index) => {
|
||||||
let totalle = eliminated_globals.iter().take_while(|i| (**i as u32) < *global_index).count();
|
let totalle = eliminated_globals.iter().take_while(|i| (**i as u32) < *global_index).count();
|
||||||
*global_index -= totalle as u32;
|
*global_index -= totalle as u32;
|
||||||
},
|
},
|
||||||
@@ -265,13 +266,13 @@ pub fn optimize(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&mut elements::Section::Global(ref mut global_section) => {
|
elements::Section::Global(global_section) => {
|
||||||
for ref mut global_entry in global_section.entries_mut() {
|
for global_entry in global_section.entries_mut() {
|
||||||
update_global_index(global_entry.init_expr_mut().code_mut(), &eliminated_globals)
|
update_global_index(global_entry.init_expr_mut().code_mut(), &eliminated_globals)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&mut elements::Section::Data(ref mut data_section) => {
|
elements::Section::Data(data_section) => {
|
||||||
for ref mut segment in data_section.entries_mut() {
|
for segment in data_section.entries_mut() {
|
||||||
update_global_index(
|
update_global_index(
|
||||||
segment
|
segment
|
||||||
.offset_mut()
|
.offset_mut()
|
||||||
@@ -282,8 +283,8 @@ pub fn optimize(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&mut elements::Section::Element(ref mut elements_section) => {
|
elements::Section::Element(elements_section) => {
|
||||||
for ref mut segment in elements_section.entries_mut() {
|
for segment in elements_section.entries_mut() {
|
||||||
update_global_index(
|
update_global_index(
|
||||||
segment
|
segment
|
||||||
.offset_mut()
|
.offset_mut()
|
||||||
@@ -299,9 +300,9 @@ pub fn optimize(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&mut elements::Section::Name(ref mut name_section) => {
|
elements::Section::Name(name_section) => {
|
||||||
if let Some(ref mut func_name) = name_section.functions_mut() {
|
if let Some(func_name) = name_section.functions_mut() {
|
||||||
let mut func_name_map = mem::replace(func_name.names_mut(), elements::IndexMap::default());
|
let mut func_name_map = mem::take(func_name.names_mut());
|
||||||
for index in &eliminated_funcs {
|
for index in &eliminated_funcs {
|
||||||
func_name_map.remove(*index as u32);
|
func_name_map.remove(*index as u32);
|
||||||
}
|
}
|
||||||
@@ -312,8 +313,8 @@ pub fn optimize(
|
|||||||
*func_name.names_mut() = updated_map;
|
*func_name.names_mut() = updated_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref mut local_name) = name_section.locals_mut() {
|
if let Some(local_name) = name_section.locals_mut() {
|
||||||
let mut local_names_map = mem::replace(local_name.local_names_mut(), elements::IndexMap::default());
|
let mut local_names_map = mem::take(local_name.local_names_mut());
|
||||||
for index in &eliminated_funcs {
|
for index in &eliminated_funcs {
|
||||||
local_names_map.remove(*index as u32);
|
local_names_map.remove(*index as u32);
|
||||||
}
|
}
|
||||||
@@ -336,7 +337,7 @@ pub fn optimize(
|
|||||||
pub fn update_call_index(instructions: &mut elements::Instructions, eliminated_indices: &[usize]) {
|
pub fn update_call_index(instructions: &mut elements::Instructions, eliminated_indices: &[usize]) {
|
||||||
use parity_wasm::elements::Instruction::*;
|
use parity_wasm::elements::Instruction::*;
|
||||||
for instruction in instructions.elements_mut().iter_mut() {
|
for instruction in instructions.elements_mut().iter_mut() {
|
||||||
if let &mut Call(ref mut call_index) = instruction {
|
if let Call(call_index) = instruction {
|
||||||
let totalle = eliminated_indices.iter().take_while(|i| (**i as u32) < *call_index).count();
|
let totalle = eliminated_indices.iter().take_while(|i| (**i as u32) < *call_index).count();
|
||||||
trace!("rewired call {} -> call {}", *call_index, *call_index - totalle as u32);
|
trace!("rewired call {} -> call {}", *call_index, *call_index - totalle as u32);
|
||||||
*call_index -= totalle as u32;
|
*call_index -= totalle as u32;
|
||||||
@@ -349,7 +350,7 @@ pub fn update_global_index(instructions: &mut Vec<elements::Instruction>, elimin
|
|||||||
use parity_wasm::elements::Instruction::*;
|
use parity_wasm::elements::Instruction::*;
|
||||||
for instruction in instructions.iter_mut() {
|
for instruction in instructions.iter_mut() {
|
||||||
match instruction {
|
match instruction {
|
||||||
&mut GetGlobal(ref mut index) | &mut SetGlobal(ref mut index) => {
|
GetGlobal(index) | SetGlobal(index) => {
|
||||||
let totalle = eliminated_indices.iter().take_while(|i| (**i as u32) < *index).count();
|
let totalle = eliminated_indices.iter().take_while(|i| (**i as u32) < *index).count();
|
||||||
trace!("rewired global {} -> global {}", *index, *index - totalle as u32);
|
trace!("rewired global {} -> global {}", *index, *index - totalle as u32);
|
||||||
*index -= totalle as u32;
|
*index -= totalle as u32;
|
||||||
@@ -363,7 +364,7 @@ pub fn update_global_index(instructions: &mut Vec<elements::Instruction>, elimin
|
|||||||
pub fn update_type_index(instructions: &mut elements::Instructions, eliminated_indices: &[usize]) {
|
pub fn update_type_index(instructions: &mut elements::Instructions, eliminated_indices: &[usize]) {
|
||||||
use parity_wasm::elements::Instruction::*;
|
use parity_wasm::elements::Instruction::*;
|
||||||
for instruction in instructions.elements_mut().iter_mut() {
|
for instruction in instructions.elements_mut().iter_mut() {
|
||||||
if let &mut CallIndirect(ref mut call_index, _) = instruction {
|
if let CallIndirect(call_index, _) = instruction {
|
||||||
let totalle = eliminated_indices.iter().take_while(|i| (**i as u32) < *call_index).count();
|
let totalle = eliminated_indices.iter().take_while(|i| (**i as u32) < *call_index).count();
|
||||||
trace!("rewired call_indrect {} -> call_indirect {}", *call_index, *call_index - totalle as u32);
|
trace!("rewired call_indrect {} -> call_indirect {}", *call_index, *call_index - totalle as u32);
|
||||||
*call_index -= totalle as u32;
|
*call_index -= totalle as u32;
|
||||||
@@ -371,54 +372,54 @@ pub fn update_type_index(instructions: &mut elements::Instructions, eliminated_i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn import_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut elements::ImportSection> {
|
pub fn import_section(module: &mut elements::Module) -> Option<&mut elements::ImportSection> {
|
||||||
for section in module.sections_mut() {
|
for section in module.sections_mut() {
|
||||||
if let &mut elements::Section::Import(ref mut sect) = section {
|
if let elements::Section::Import(sect) = section {
|
||||||
return Some(sect);
|
return Some(sect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn global_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut elements::GlobalSection> {
|
pub fn global_section(module: &mut elements::Module) -> Option<&mut elements::GlobalSection> {
|
||||||
for section in module.sections_mut() {
|
for section in module.sections_mut() {
|
||||||
if let &mut elements::Section::Global(ref mut sect) = section {
|
if let elements::Section::Global(sect) = section {
|
||||||
return Some(sect);
|
return Some(sect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn function_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut elements::FunctionSection> {
|
pub fn function_section(module: &mut elements::Module) -> Option<&mut elements::FunctionSection> {
|
||||||
for section in module.sections_mut() {
|
for section in module.sections_mut() {
|
||||||
if let &mut elements::Section::Function(ref mut sect) = section {
|
if let elements::Section::Function(sect) = section {
|
||||||
return Some(sect);
|
return Some(sect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn code_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut elements::CodeSection> {
|
pub fn code_section(module: &mut elements::Module) -> Option<&mut elements::CodeSection> {
|
||||||
for section in module.sections_mut() {
|
for section in module.sections_mut() {
|
||||||
if let &mut elements::Section::Code(ref mut sect) = section {
|
if let elements::Section::Code(sect) = section {
|
||||||
return Some(sect);
|
return Some(sect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn export_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut elements::ExportSection> {
|
pub fn export_section(module: &mut elements::Module) -> Option<&mut elements::ExportSection> {
|
||||||
for section in module.sections_mut() {
|
for section in module.sections_mut() {
|
||||||
if let &mut elements::Section::Export(ref mut sect) = section {
|
if let elements::Section::Export(sect) = section {
|
||||||
return Some(sect);
|
return Some(sect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut elements::TypeSection> {
|
pub fn type_section(module: &mut elements::Module) -> Option<&mut elements::TypeSection> {
|
||||||
for section in module.sections_mut() {
|
for section in module.sections_mut() {
|
||||||
if let &mut elements::Section::Type(ref mut sect) = section {
|
if let elements::Section::Type(sect) = section {
|
||||||
return Some(sect);
|
return Some(sect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-14
@@ -56,7 +56,7 @@ pub fn pack_instance(raw_module: Vec<u8>, mut ctor_module: elements::Module, tar
|
|||||||
.find(|entry| target.symbols().create == entry.field()).ok_or_else(|| Error::NoCreateSymbol(target.symbols().create))?;
|
.find(|entry| target.symbols().create == entry.field()).ok_or_else(|| Error::NoCreateSymbol(target.symbols().create))?;
|
||||||
|
|
||||||
let function_index: usize = match found_entry.internal() {
|
let function_index: usize = match found_entry.internal() {
|
||||||
&Internal::Function(index) => index as usize,
|
Internal::Function(index) => *index as usize,
|
||||||
_ => { return Err(Error::InvalidCreateMember(target.symbols().create)) },
|
_ => { return Err(Error::InvalidCreateMember(target.symbols().create)) },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ pub fn pack_instance(raw_module: Vec<u8>, mut ctor_module: elements::Module, tar
|
|||||||
.entries().get(function_index - ctor_import_functions).ok_or(Error::MalformedModule)?
|
.entries().get(function_index - ctor_import_functions).ok_or(Error::MalformedModule)?
|
||||||
.type_ref();
|
.type_ref();
|
||||||
|
|
||||||
let &elements::Type::Function(ref func) = ctor_module.type_section().ok_or(Error::NoTypeSection)?
|
let elements::Type::Function(func) = ctor_module.type_section().ok_or(Error::NoTypeSection)?
|
||||||
.types().get(type_id as usize).ok_or(Error::MalformedModule)?;
|
.types().get(type_id as usize).ok_or(Error::MalformedModule)?;
|
||||||
|
|
||||||
// Deploy should have no arguments and also should return nothing
|
// Deploy should have no arguments and also should return nothing
|
||||||
@@ -112,21 +112,21 @@ pub fn pack_instance(raw_module: Vec<u8>, mut ctor_module: elements::Module, tar
|
|||||||
let ret_func = ctor_module.import_count(ImportCountType::Function) as u32 - 1;
|
let ret_func = ctor_module.import_count(ImportCountType::Function) as u32 - 1;
|
||||||
|
|
||||||
for section in ctor_module.sections_mut() {
|
for section in ctor_module.sections_mut() {
|
||||||
match *section {
|
match section {
|
||||||
elements::Section::Code(ref mut code_section) => {
|
elements::Section::Code(code_section) => {
|
||||||
for ref mut func_body in code_section.bodies_mut() {
|
for func_body in code_section.bodies_mut() {
|
||||||
update_call_index(func_body.code_mut(), ret_func);
|
update_call_index(func_body.code_mut(), ret_func);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
elements::Section::Export(ref mut export_section) => {
|
elements::Section::Export(export_section) => {
|
||||||
for ref mut export in export_section.entries_mut() {
|
for export in export_section.entries_mut() {
|
||||||
if let &mut elements::Internal::Function(ref mut func_index) = export.internal_mut() {
|
if let elements::Internal::Function(func_index) = export.internal_mut() {
|
||||||
if *func_index >= ret_func { *func_index += 1}
|
if *func_index >= ret_func { *func_index += 1}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
elements::Section::Element(ref mut elements_section) => {
|
elements::Section::Element(elements_section) => {
|
||||||
for ref mut segment in elements_section.entries_mut() {
|
for segment in elements_section.entries_mut() {
|
||||||
// update all indirect call addresses initial values
|
// update all indirect call addresses initial values
|
||||||
for func_index in segment.members_mut() {
|
for func_index in segment.members_mut() {
|
||||||
if *func_index >= ret_func { *func_index += 1}
|
if *func_index >= ret_func { *func_index += 1}
|
||||||
@@ -150,7 +150,7 @@ pub fn pack_instance(raw_module: Vec<u8>, mut ctor_module: elements::Module, tar
|
|||||||
if ctor_module
|
if ctor_module
|
||||||
.sections()
|
.sections()
|
||||||
.iter()
|
.iter()
|
||||||
.find(|section| match **section { Section::Data(ref _d) => true, _ => false })
|
.find(|section| matches!(**section, Section::Data(_)))
|
||||||
.is_none() {
|
.is_none() {
|
||||||
// DataSection has to be the last non-custom section according the to the spec
|
// DataSection has to be the last non-custom section according the to the spec
|
||||||
ctor_module.sections_mut().push(Section::Data(DataSection::with_entries(vec![])));
|
ctor_module.sections_mut().push(Section::Data(DataSection::with_entries(vec![])));
|
||||||
@@ -160,8 +160,8 @@ pub fn pack_instance(raw_module: Vec<u8>, mut ctor_module: elements::Module, tar
|
|||||||
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() {
|
||||||
if let &mut Section::Data(ref mut data_section) = section {
|
if let Section::Data(data_section) = section {
|
||||||
let (index, offset) = if let Some(ref entry) = data_section.entries().iter().last() {
|
let (index, offset) = if let Some(entry) = data_section.entries().iter().last() {
|
||||||
let init_expr = entry
|
let init_expr = entry
|
||||||
.offset()
|
.offset()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -202,7 +202,7 @@ pub fn pack_instance(raw_module: Vec<u8>, mut ctor_module: elements::Module, tar
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
for section in new_module.sections_mut() {
|
for section in new_module.sections_mut() {
|
||||||
if let &mut Section::Export(ref mut export_section) = section {
|
if let Section::Export(export_section) = section {
|
||||||
for entry in export_section.entries_mut().iter_mut() {
|
for entry in export_section.entries_mut().iter_mut() {
|
||||||
if target.symbols().create == entry.field() {
|
if target.symbols().create == entry.field() {
|
||||||
// change `create` symbol export name into default `call` symbol name.
|
// change `create` symbol export name into default `call` symbol name.
|
||||||
|
|||||||
+11
-8
@@ -28,7 +28,7 @@ impl<T> Entry<T> {
|
|||||||
/// New entity.
|
/// New entity.
|
||||||
pub fn new(val: T, index: usize) -> Entry<T> {
|
pub fn new(val: T, index: usize) -> Entry<T> {
|
||||||
Entry {
|
Entry {
|
||||||
val: val,
|
val,
|
||||||
index: EntryOrigin::Index(index),
|
index: EntryOrigin::Index(index),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ impl<T> Entry<T> {
|
|||||||
/// New detached entry.
|
/// New detached entry.
|
||||||
pub fn new_detached(val: T) -> Entry<T> {
|
pub fn new_detached(val: T) -> Entry<T> {
|
||||||
Entry {
|
Entry {
|
||||||
val: val,
|
val,
|
||||||
index: EntryOrigin::Detached,
|
index: EntryOrigin::Detached,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,7 +152,7 @@ impl<T> RefList<T> {
|
|||||||
/// internal indices of other entries might be updated.
|
/// internal indices of other entries might be updated.
|
||||||
pub fn begin_insert(&mut self, at: usize) -> InsertTransaction<T> {
|
pub fn begin_insert(&mut self, at: usize) -> InsertTransaction<T> {
|
||||||
InsertTransaction {
|
InsertTransaction {
|
||||||
at: at,
|
at,
|
||||||
list: self,
|
list: self,
|
||||||
items: Vec::new(),
|
items: Vec::new(),
|
||||||
}
|
}
|
||||||
@@ -201,17 +201,15 @@ impl<T> RefList<T> {
|
|||||||
let total_less = indices.iter()
|
let total_less = indices.iter()
|
||||||
.take_while(|x| **x < entry.order().expect("Items in the list always have order; qed"))
|
.take_while(|x| **x < entry.order().expect("Items in the list always have order; qed"))
|
||||||
.count();
|
.count();
|
||||||
match entry.index {
|
match &mut entry.index {
|
||||||
EntryOrigin::Detached => unreachable!("Items in the list always have order!"),
|
EntryOrigin::Detached => unreachable!("Items in the list always have order!"),
|
||||||
EntryOrigin::Index(ref mut idx) => { *idx -= total_less; },
|
EntryOrigin::Index(idx) => { *idx -= total_less; },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut total_removed = 0;
|
for (total_removed, idx) in indices.iter().enumerate() {
|
||||||
for idx in indices {
|
|
||||||
let detached = self.items.remove(*idx - total_removed);
|
let detached = self.items.remove(*idx - total_removed);
|
||||||
detached.write().index = EntryOrigin::Detached;
|
detached.write().index = EntryOrigin::Detached;
|
||||||
total_removed += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,6 +256,11 @@ impl<T> RefList<T> {
|
|||||||
self.items.len()
|
self.items.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true iff len == 0.
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.len() == 0
|
||||||
|
}
|
||||||
|
|
||||||
/// Clone entry (reference counting object to item) by index.
|
/// Clone entry (reference counting object to item) by index.
|
||||||
///
|
///
|
||||||
/// Will panic if index out of bounds.
|
/// Will panic if index out of bounds.
|
||||||
|
|||||||
+2
-2
@@ -285,11 +285,11 @@ impl Default for Set {
|
|||||||
|
|
||||||
impl Set {
|
impl Set {
|
||||||
pub fn new(regular: u32, entries: Map<InstructionType, Metering>) -> Self {
|
pub fn new(regular: u32, entries: Map<InstructionType, Metering>) -> Self {
|
||||||
Set { regular: regular, entries: entries, grow: 0 }
|
Set { regular, entries, grow: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process(&self, instruction: &elements::Instruction) -> Result<u32, ()> {
|
pub fn process(&self, instruction: &elements::Instruction) -> Result<u32, ()> {
|
||||||
match self.entries.get(&InstructionType::op(instruction)).map(|x| *x) {
|
match self.entries.get(&InstructionType::op(instruction)).cloned() {
|
||||||
None | Some(Metering::Regular) => Ok(self.regular),
|
None | Some(Metering::Regular) => Ok(self.regular),
|
||||||
Some(Metering::Forbidden) => Err(()),
|
Some(Metering::Forbidden) => Err(()),
|
||||||
Some(Metering::Fixed(val)) => Ok(val),
|
Some(Metering::Fixed(val)) => Ok(val),
|
||||||
|
|||||||
+8
-7
@@ -5,14 +5,15 @@ use byteorder::{ LittleEndian, ByteOrder };
|
|||||||
pub fn inject_runtime_type(module: Module, runtime_type: [u8; 4], runtime_version: u32) -> Module {
|
pub fn inject_runtime_type(module: Module, runtime_type: [u8; 4], runtime_version: u32) -> Module {
|
||||||
let runtime_type: u32 = LittleEndian::read_u32(&runtime_type);
|
let runtime_type: u32 = LittleEndian::read_u32(&runtime_type);
|
||||||
let globals_count: u32 = match module.global_section() {
|
let globals_count: u32 = match module.global_section() {
|
||||||
Some(ref section) => section.entries().len() as u32,
|
Some(section) => section.entries().len() as u32,
|
||||||
None => 0
|
None => 0
|
||||||
};
|
};
|
||||||
let imported_globals_count: u32 = match module.import_section() {
|
let imported_globals_count: u32 = match module.import_section() {
|
||||||
Some(ref section) => section.entries().iter().filter(|e| match *e.external() {
|
Some(section) => section
|
||||||
External::Global(ref _a) => true,
|
.entries()
|
||||||
_ => false
|
.iter()
|
||||||
}).count() as u32,
|
.filter(|e| matches!(*e.external(), External::Global(_)))
|
||||||
|
.count() as u32,
|
||||||
None => 0
|
None => 0
|
||||||
};
|
};
|
||||||
let total_globals_count: u32 = globals_count + imported_globals_count;
|
let total_globals_count: u32 = globals_count + imported_globals_count;
|
||||||
@@ -39,7 +40,7 @@ mod tests {
|
|||||||
let global_section = module.global_section().expect("Global section expected");
|
let global_section = module.global_section().expect("Global section expected");
|
||||||
assert_eq!(3, global_section.entries().len());
|
assert_eq!(3, global_section.entries().len());
|
||||||
let export_section = module.export_section().expect("Export section expected");
|
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().any(|e| e.field() == "RUNTIME_TYPE"));
|
||||||
assert!(export_section.entries().iter().find(|e| e.field() == "RUNTIME_VERSION" ).is_some());
|
assert!(export_section.entries().iter().any(|e| e.field() == "RUNTIME_VERSION"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ pub(crate) fn compute(func_idx: u32, module: &elements::Module) -> Result<u32, E
|
|||||||
.get(func_idx as usize)
|
.get(func_idx as usize)
|
||||||
.ok_or_else(|| Error("Function is not found in func section".into()))?
|
.ok_or_else(|| Error("Function is not found in func section".into()))?
|
||||||
.type_ref();
|
.type_ref();
|
||||||
let Type::Function(ref func_signature) = *type_section
|
let Type::Function(func_signature) = type_section
|
||||||
.types()
|
.types()
|
||||||
.get(func_sig_idx as usize)
|
.get(func_sig_idx as usize)
|
||||||
.ok_or_else(|| Error("Function is not found in func section".into()))?;
|
.ok_or_else(|| Error("Function is not found in func section".into()))?;
|
||||||
@@ -200,10 +200,10 @@ pub(crate) fn compute(func_idx: u32, module: &elements::Module) -> Result<u32, E
|
|||||||
let opcode = &instructions.elements()[pc];
|
let opcode = &instructions.elements()[pc];
|
||||||
trace!(target: "max_height", "{:?}", opcode);
|
trace!(target: "max_height", "{:?}", opcode);
|
||||||
|
|
||||||
match *opcode {
|
match opcode {
|
||||||
Nop => {}
|
Nop => {}
|
||||||
Block(ty) | Loop(ty) | If(ty) => {
|
Block(ty) | Loop(ty) | If(ty) => {
|
||||||
let end_arity = if ty == BlockType::NoResult { 0 } else { 1 };
|
let end_arity = if *ty == BlockType::NoResult { 0 } else { 1 };
|
||||||
let branch_arity = if let Loop(_) = *opcode { 0 } else { end_arity };
|
let branch_arity = if let Loop(_) = *opcode { 0 } else { end_arity };
|
||||||
let height = stack.height();
|
let height = stack.height();
|
||||||
stack.push_frame(Frame {
|
stack.push_frame(Frame {
|
||||||
@@ -227,7 +227,7 @@ pub(crate) fn compute(func_idx: u32, module: &elements::Module) -> Result<u32, E
|
|||||||
}
|
}
|
||||||
Br(target) => {
|
Br(target) => {
|
||||||
// Pop values for the destination block result.
|
// Pop values for the destination block result.
|
||||||
let target_arity = stack.frame(target)?.branch_arity;
|
let target_arity = stack.frame(*target)?.branch_arity;
|
||||||
stack.pop_values(target_arity)?;
|
stack.pop_values(target_arity)?;
|
||||||
|
|
||||||
// This instruction unconditionally transfers control to the specified block,
|
// This instruction unconditionally transfers control to the specified block,
|
||||||
@@ -236,7 +236,7 @@ pub(crate) fn compute(func_idx: u32, module: &elements::Module) -> Result<u32, E
|
|||||||
}
|
}
|
||||||
BrIf(target) => {
|
BrIf(target) => {
|
||||||
// Pop values for the destination block result.
|
// Pop values for the destination block result.
|
||||||
let target_arity = stack.frame(target)?.branch_arity;
|
let target_arity = stack.frame(*target)?.branch_arity;
|
||||||
stack.pop_values(target_arity)?;
|
stack.pop_values(target_arity)?;
|
||||||
|
|
||||||
// Pop condition value.
|
// Pop condition value.
|
||||||
@@ -245,7 +245,7 @@ pub(crate) fn compute(func_idx: u32, module: &elements::Module) -> Result<u32, E
|
|||||||
// Push values back.
|
// Push values back.
|
||||||
stack.push_values(target_arity)?;
|
stack.push_values(target_arity)?;
|
||||||
}
|
}
|
||||||
BrTable(ref br_table_data) => {
|
BrTable(br_table_data) => {
|
||||||
let arity_of_default = stack.frame(br_table_data.default)?.branch_arity;
|
let arity_of_default = stack.frame(br_table_data.default)?.branch_arity;
|
||||||
|
|
||||||
// Check that all jump targets have an equal arities.
|
// Check that all jump targets have an equal arities.
|
||||||
@@ -273,7 +273,7 @@ pub(crate) fn compute(func_idx: u32, module: &elements::Module) -> Result<u32, E
|
|||||||
stack.mark_unreachable()?;
|
stack.mark_unreachable()?;
|
||||||
}
|
}
|
||||||
Call(idx) => {
|
Call(idx) => {
|
||||||
let ty = resolve_func_type(idx, module)?;
|
let ty = resolve_func_type(*idx, module)?;
|
||||||
|
|
||||||
// Pop values for arguments of the function.
|
// Pop values for arguments of the function.
|
||||||
stack.pop_values(ty.params().len() as u32)?;
|
stack.pop_values(ty.params().len() as u32)?;
|
||||||
@@ -283,9 +283,9 @@ pub(crate) fn compute(func_idx: u32, module: &elements::Module) -> Result<u32, E
|
|||||||
stack.push_values(callee_arity)?;
|
stack.push_values(callee_arity)?;
|
||||||
}
|
}
|
||||||
CallIndirect(x, _) => {
|
CallIndirect(x, _) => {
|
||||||
let Type::Function(ref ty) = *type_section
|
let Type::Function(ty) = type_section
|
||||||
.types()
|
.types()
|
||||||
.get(x as usize)
|
.get(*x as usize)
|
||||||
.ok_or_else(|| Error("Type not found".into()))?;
|
.ok_or_else(|| Error("Type not found".into()))?;
|
||||||
|
|
||||||
// Pop the offset into the function table.
|
// Pop the offset into the function table.
|
||||||
@@ -496,7 +496,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn yet_another_test() {
|
fn yet_another_test() {
|
||||||
const SOURCE: &'static str = r#"
|
const SOURCE: &str = r#"
|
||||||
(module
|
(module
|
||||||
(memory 0)
|
(memory 0)
|
||||||
(func
|
(func
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ fn generate_stack_height_global(module: &mut elements::Module) -> u32 {
|
|||||||
|
|
||||||
// Try to find an existing global section.
|
// Try to find an existing global section.
|
||||||
for section in module.sections_mut() {
|
for section in module.sections_mut() {
|
||||||
if let elements::Section::Global(ref mut gs) = *section {
|
if let elements::Section::Global(gs) = section {
|
||||||
gs.entries_mut().push(global_entry);
|
gs.entries_mut().push(global_entry);
|
||||||
return (gs.entries().len() as u32) - 1;
|
return (gs.entries().len() as u32) - 1;
|
||||||
}
|
}
|
||||||
@@ -212,7 +212,7 @@ fn compute_stack_cost(func_idx: u32, module: &elements::Module) -> Result<u32, E
|
|||||||
|
|
||||||
fn instrument_functions(ctx: &mut Context, module: &mut elements::Module) -> Result<(), Error> {
|
fn instrument_functions(ctx: &mut Context, module: &mut elements::Module) -> Result<(), Error> {
|
||||||
for section in module.sections_mut() {
|
for section in module.sections_mut() {
|
||||||
if let elements::Section::Code(ref mut code_section) = *section {
|
if let elements::Section::Code(code_section) = section {
|
||||||
for func_body in code_section.bodies_mut() {
|
for func_body in code_section.bodies_mut() {
|
||||||
let opcodes = func_body.code_mut();
|
let opcodes = func_body.code_mut();
|
||||||
instrument_function(ctx, opcodes)?;
|
instrument_function(ctx, opcodes)?;
|
||||||
@@ -270,8 +270,8 @@ fn instrument_function(
|
|||||||
|
|
||||||
let action: Action = {
|
let action: Action = {
|
||||||
let instruction = &instructions.elements()[cursor];
|
let instruction = &instructions.elements()[cursor];
|
||||||
match *instruction {
|
match instruction {
|
||||||
Call(ref callee_idx) => {
|
Call(callee_idx) => {
|
||||||
let callee_stack_cost = ctx
|
let callee_stack_cost = ctx
|
||||||
.stack_cost(*callee_idx)
|
.stack_cost(*callee_idx)
|
||||||
.ok_or_else(||
|
.ok_or_else(||
|
||||||
@@ -347,8 +347,8 @@ fn resolve_func_type(
|
|||||||
.expect("function import count is not zero; import section must exists; qed")
|
.expect("function import count is not zero; import section must exists; qed")
|
||||||
.entries()
|
.entries()
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|entry| match *entry.external() {
|
.filter_map(|entry| match entry.external() {
|
||||||
elements::External::Function(ref idx) => Some(*idx),
|
elements::External::Function(idx) => Some(*idx),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.nth(func_idx as usize)
|
.nth(func_idx as usize)
|
||||||
@@ -363,7 +363,7 @@ fn resolve_func_type(
|
|||||||
.ok_or_else(|| Error(format!("Function at index {} is not defined", func_idx)))?
|
.ok_or_else(|| Error(format!("Function at index {} is not defined", func_idx)))?
|
||||||
.type_ref()
|
.type_ref()
|
||||||
};
|
};
|
||||||
let Type::Function(ref ty) = *types.get(sig_idx as usize).ok_or_else(|| {
|
let Type::Function(ty) = types.get(sig_idx as usize).ok_or_else(|| {
|
||||||
Error(format!(
|
Error(format!(
|
||||||
"Signature {} (specified by func {}) isn't defined",
|
"Signature {} (specified by func {}) isn't defined",
|
||||||
sig_idx, func_idx
|
sig_idx, func_idx
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ pub(crate) fn generate_thunks(
|
|||||||
let start_func_idx = module
|
let start_func_idx = module
|
||||||
.start_section();
|
.start_section();
|
||||||
|
|
||||||
let exported_func_indices = exports.iter().filter_map(|entry| match *entry.internal() {
|
let exported_func_indices = exports.iter().filter_map(|entry| match entry.internal() {
|
||||||
Internal::Function(ref function_idx) => Some(*function_idx),
|
Internal::Function(function_idx) => Some(*function_idx),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
let table_func_indices = elem_segments
|
let table_func_indices = elem_segments
|
||||||
@@ -119,7 +119,7 @@ pub(crate) fn generate_thunks(
|
|||||||
let fixup = |function_idx: &mut u32| {
|
let fixup = |function_idx: &mut u32| {
|
||||||
// Check whether this function is in replacement_map, since
|
// Check whether this function is in replacement_map, since
|
||||||
// we can skip thunk generation (e.g. if stack_cost of function is 0).
|
// we can skip thunk generation (e.g. if stack_cost of function is 0).
|
||||||
if let Some(ref thunk) = replacement_map.get(function_idx) {
|
if let Some(thunk) = replacement_map.get(function_idx) {
|
||||||
*function_idx = thunk
|
*function_idx = thunk
|
||||||
.idx
|
.idx
|
||||||
.expect("At this point an index must be assigned to each thunk");
|
.expect("At this point an index must be assigned to each thunk");
|
||||||
@@ -127,22 +127,22 @@ pub(crate) fn generate_thunks(
|
|||||||
};
|
};
|
||||||
|
|
||||||
for section in module.sections_mut() {
|
for section in module.sections_mut() {
|
||||||
match *section {
|
match section {
|
||||||
elements::Section::Export(ref mut export_section) => {
|
elements::Section::Export(export_section) => {
|
||||||
for entry in export_section.entries_mut() {
|
for entry in export_section.entries_mut() {
|
||||||
if let Internal::Function(ref mut function_idx) = *entry.internal_mut() {
|
if let Internal::Function(function_idx) = entry.internal_mut() {
|
||||||
fixup(function_idx)
|
fixup(function_idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elements::Section::Element(ref mut elem_section) => {
|
elements::Section::Element(elem_section) => {
|
||||||
for segment in elem_section.entries_mut() {
|
for segment in elem_section.entries_mut() {
|
||||||
for function_idx in segment.members_mut() {
|
for function_idx in segment.members_mut() {
|
||||||
fixup(function_idx)
|
fixup(function_idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elements::Section::Start(ref mut start_idx) => {
|
elements::Section::Start(start_idx) => {
|
||||||
fixup(start_idx)
|
fixup(start_idx)
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|||||||
+8
-8
@@ -19,7 +19,7 @@ pub fn resolve_function(module: &elements::Module, index: u32) -> Symbol {
|
|||||||
let mut functions = 0;
|
let mut functions = 0;
|
||||||
if let Some(import_section) = module.import_section() {
|
if let Some(import_section) = module.import_section() {
|
||||||
for (item_index, item) in import_section.entries().iter().enumerate() {
|
for (item_index, item) in import_section.entries().iter().enumerate() {
|
||||||
if let &elements::External::Function(_) = item.external() {
|
if let elements::External::Function(_) = item.external() {
|
||||||
if functions == index {
|
if functions == index {
|
||||||
return Symbol::Import(item_index as usize);
|
return Symbol::Import(item_index as usize);
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ pub fn resolve_global(module: &elements::Module, index: u32) -> Symbol {
|
|||||||
let mut globals = 0;
|
let mut globals = 0;
|
||||||
if let Some(import_section) = module.import_section() {
|
if let Some(import_section) = module.import_section() {
|
||||||
for (item_index, item) in import_section.entries().iter().enumerate() {
|
for (item_index, item) in import_section.entries().iter().enumerate() {
|
||||||
if let &elements::External::Global(_) = item.external() {
|
if let elements::External::Global(_) = item.external() {
|
||||||
if globals == index {
|
if globals == index {
|
||||||
return Symbol::Import(item_index as usize);
|
return Symbol::Import(item_index as usize);
|
||||||
}
|
}
|
||||||
@@ -84,15 +84,15 @@ pub fn expand_symbols(module: &elements::Module, set: &mut Set<Symbol>) {
|
|||||||
Export(idx) => {
|
Export(idx) => {
|
||||||
let entry = &module.export_section().expect("Export section to exist").entries()[idx];
|
let entry = &module.export_section().expect("Export section to exist").entries()[idx];
|
||||||
match entry.internal() {
|
match entry.internal() {
|
||||||
&elements::Internal::Function(func_idx) => {
|
elements::Internal::Function(func_idx) => {
|
||||||
let symbol = resolve_function(module, func_idx);
|
let symbol = resolve_function(module, *func_idx);
|
||||||
if !stop.contains(&symbol) {
|
if !stop.contains(&symbol) {
|
||||||
fringe.push(symbol);
|
fringe.push(symbol);
|
||||||
}
|
}
|
||||||
set.insert(symbol);
|
set.insert(symbol);
|
||||||
},
|
},
|
||||||
&elements::Internal::Global(global_idx) => {
|
elements::Internal::Global(global_idx) => {
|
||||||
let symbol = resolve_global(module, global_idx);
|
let symbol = resolve_global(module, *global_idx);
|
||||||
if !stop.contains(&symbol) {
|
if !stop.contains(&symbol) {
|
||||||
fringe.push(symbol);
|
fringe.push(symbol);
|
||||||
}
|
}
|
||||||
@@ -103,8 +103,8 @@ pub fn expand_symbols(module: &elements::Module, set: &mut Set<Symbol>) {
|
|||||||
},
|
},
|
||||||
Import(idx) => {
|
Import(idx) => {
|
||||||
let entry = &module.import_section().expect("Import section to exist").entries()[idx];
|
let entry = &module.import_section().expect("Import section to exist").entries()[idx];
|
||||||
if let &elements::External::Function(type_idx) = entry.external() {
|
if let elements::External::Function(type_idx) = entry.external() {
|
||||||
let type_symbol = Symbol::Type(type_idx as usize);
|
let type_symbol = Symbol::Type(*type_idx as usize);
|
||||||
if !stop.contains(&type_symbol) {
|
if !stop.contains(&type_symbol) {
|
||||||
fringe.push(type_symbol);
|
fringe.push(type_symbol);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user