mirror of
https://github.com/fluencelabs/wasm-utils
synced 2025-04-22 21:32:22 +00:00
code mapping
This commit is contained in:
parent
d60340762b
commit
48c1c6e72a
82
src/graph.rs
82
src/graph.rs
@ -18,11 +18,16 @@ impl<T> From<&elements::ImportEntry> for ImportedOrDeclared<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type FuncOrigin = ImportedOrDeclared<Vec<Instruction>>;
|
pub type FuncOrigin = ImportedOrDeclared<FuncBody>;
|
||||||
pub type GlobalOrigin = ImportedOrDeclared<Vec<Instruction>>;
|
pub type GlobalOrigin = ImportedOrDeclared<Vec<Instruction>>;
|
||||||
pub type MemoryOrigin = ImportedOrDeclared;
|
pub type MemoryOrigin = ImportedOrDeclared;
|
||||||
pub type TableOrigin = ImportedOrDeclared;
|
pub type TableOrigin = ImportedOrDeclared;
|
||||||
|
|
||||||
|
pub struct FuncBody {
|
||||||
|
pub locals: Vec<elements::Local>,
|
||||||
|
pub code: Vec<Instruction>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Func {
|
pub struct Func {
|
||||||
pub type_ref: EntryRef<elements::Type>,
|
pub type_ref: EntryRef<elements::Type>,
|
||||||
pub origin: FuncOrigin,
|
pub origin: FuncOrigin,
|
||||||
@ -37,6 +42,9 @@ pub struct Global {
|
|||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
Plain(elements::Instruction),
|
Plain(elements::Instruction),
|
||||||
Call(EntryRef<Func>),
|
Call(EntryRef<Func>),
|
||||||
|
CallIndirect(EntryRef<elements::Type>, u8),
|
||||||
|
GetGlobal(EntryRef<Global>),
|
||||||
|
SetGlobal(EntryRef<Global>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Memory {
|
pub struct Memory {
|
||||||
@ -93,11 +101,41 @@ pub struct Module {
|
|||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
|
|
||||||
|
fn map_instructions(&self, instructions: &[elements::Instruction]) -> Vec<Instruction> {
|
||||||
|
use parity_wasm::elements::Instruction::*;
|
||||||
|
instructions.iter().map(|instruction| match instruction {
|
||||||
|
Call(func_idx) => Instruction::Call(self.funcs.clone_ref(*func_idx as usize)),
|
||||||
|
CallIndirect(type_idx, arg2) =>
|
||||||
|
Instruction::CallIndirect(
|
||||||
|
self.types.clone_ref(*type_idx as usize),
|
||||||
|
*arg2,
|
||||||
|
),
|
||||||
|
SetGlobal(global_idx) =>
|
||||||
|
Instruction::SetGlobal(self.globals.clone_ref(*global_idx as usize)),
|
||||||
|
GetGlobal(global_idx) =>
|
||||||
|
Instruction::GetGlobal(self.globals.clone_ref(*global_idx as usize)),
|
||||||
|
other_instruction => Instruction::Plain(other_instruction.clone()),
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_instructions(&self, instructions: &[Instruction]) -> Vec<elements::Instruction> {
|
||||||
|
use parity_wasm::elements::Instruction::*;
|
||||||
|
instructions.iter().map(|instruction| match instruction {
|
||||||
|
Instruction::Call(func_ref) => Call(func_ref.order().expect("detached instruction!") as u32),
|
||||||
|
Instruction::CallIndirect(type_ref, arg2) => CallIndirect(type_ref.order().expect("detached instruction!") as u32, *arg2),
|
||||||
|
Instruction::SetGlobal(global_ref) => SetGlobal(global_ref.order().expect("detached instruction!") as u32),
|
||||||
|
Instruction::GetGlobal(global_ref) => GetGlobal(global_ref.order().expect("detached instruction!") as u32),
|
||||||
|
Instruction::Plain(plain) => plain.clone(),
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_elements(module: &elements::Module) -> Self {
|
pub fn from_elements(module: &elements::Module) -> Self {
|
||||||
|
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
let mut res = Module::default();
|
let mut res = Module::default();
|
||||||
|
|
||||||
|
let mut imported_functions = 0;
|
||||||
|
|
||||||
for section in module.sections() {
|
for section in module.sections() {
|
||||||
match section {
|
match section {
|
||||||
elements::Section::Type(type_section) => {
|
elements::Section::Type(type_section) => {
|
||||||
@ -111,6 +149,7 @@ impl Module {
|
|||||||
type_ref: res.types.get(f as usize).expect("validated; qed").clone(),
|
type_ref: res.types.get(f as usize).expect("validated; qed").clone(),
|
||||||
origin: entry.into(),
|
origin: entry.into(),
|
||||||
});
|
});
|
||||||
|
imported_functions += 1;
|
||||||
},
|
},
|
||||||
elements::External::Memory(m) => {
|
elements::External::Memory(m) => {
|
||||||
res.memory.push(Memory {
|
res.memory.push(Memory {
|
||||||
@ -138,8 +177,11 @@ impl Module {
|
|||||||
for f in function_section.entries() {
|
for f in function_section.entries() {
|
||||||
res.funcs.push(Func {
|
res.funcs.push(Func {
|
||||||
type_ref: res.types.get(f.type_ref() as usize).expect("validated; qed").clone(),
|
type_ref: res.types.get(f.type_ref() as usize).expect("validated; qed").clone(),
|
||||||
|
origin: ImportedOrDeclared::Declared(FuncBody {
|
||||||
|
locals: Vec::new(),
|
||||||
// code will be populated later
|
// code will be populated later
|
||||||
origin: ImportedOrDeclared::Declared(Vec::new()),
|
code: Vec::new(),
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -161,11 +203,11 @@ impl Module {
|
|||||||
},
|
},
|
||||||
elements::Section::Global(global_section) => {
|
elements::Section::Global(global_section) => {
|
||||||
for g in global_section.entries() {
|
for g in global_section.entries() {
|
||||||
|
let init_code = res.map_instructions(g.init_expr().code());
|
||||||
res.globals.push(Global {
|
res.globals.push(Global {
|
||||||
content: g.global_type().content_type(),
|
content: g.global_type().content_type(),
|
||||||
is_mut: g.global_type().is_mutable(),
|
is_mut: g.global_type().is_mutable(),
|
||||||
// TODO: init expr
|
origin: ImportedOrDeclared::Declared(init_code),
|
||||||
origin: ImportedOrDeclared::Declared(Vec::new()),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -205,9 +247,10 @@ impl Module {
|
|||||||
// SegmentLocation::WithIndex(element_segment.index(), Vec::new())
|
// SegmentLocation::WithIndex(element_segment.index(), Vec::new())
|
||||||
// };
|
// };
|
||||||
|
|
||||||
// TODO: transform instructions
|
// TODO: update parity-wasm and uncomment the above instead
|
||||||
// TODO: update parity-wasm and uncomment the above
|
let location = SegmentLocation::Default(
|
||||||
let location = SegmentLocation::Default(Vec::new());
|
res.map_instructions(element_segment.offset().code())
|
||||||
|
);
|
||||||
|
|
||||||
res.elements.push(ElementSegment {
|
res.elements.push(ElementSegment {
|
||||||
value: element_segment.members().to_vec(),
|
value: element_segment.members().to_vec(),
|
||||||
@ -215,18 +258,35 @@ impl Module {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
elements::Section::Code(code_section) => {
|
||||||
|
let mut idx = 0;
|
||||||
|
for func_body in code_section.bodies() {
|
||||||
|
let code = res.map_instructions(func_body.code().elements());
|
||||||
|
|
||||||
|
let mut func = res.funcs.get_ref(imported_functions + idx).write();
|
||||||
|
match func.origin {
|
||||||
|
ImportedOrDeclared::Declared(ref mut body) => {
|
||||||
|
body.code = code;
|
||||||
|
body.locals = func_body.locals().iter().cloned().collect();
|
||||||
|
},
|
||||||
|
_ => unreachable!("All declared functions added after imported; qed"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
elements::Section::Data(data_section) => {
|
elements::Section::Data(data_section) => {
|
||||||
for data_segment in data_section.entries() {
|
for data_segment in data_section.entries() {
|
||||||
// TODO: transform instructions
|
// TODO: update parity-wasm and use the same logic as in
|
||||||
// TODO: update parity-wasm and uncomment the above
|
// commented element segment branch
|
||||||
let location = SegmentLocation::Default(Vec::new());
|
let location = SegmentLocation::Default(
|
||||||
|
res.map_instructions(data_segment.offset().code())
|
||||||
|
);
|
||||||
|
|
||||||
res.data.push(DataSegment {
|
res.data.push(DataSegment {
|
||||||
value: data_segment.value().to_vec(),
|
value: data_segment.value().to_vec(),
|
||||||
location: location,
|
location: location,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
_ => {
|
_ => {
|
||||||
res.other.insert(idx, section.clone());
|
res.other.insert(idx, section.clone());
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,12 @@ impl<T> ::std::ops::Deref for Entry<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> ::std::ops::DerefMut for Entry<T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut T {
|
||||||
|
&mut self.val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct EntryRef<T>(Rc<RefCell<Entry<T>>>);
|
pub struct EntryRef<T>(Rc<RefCell<Entry<T>>>);
|
||||||
|
|
||||||
impl<T> Clone for EntryRef<T> {
|
impl<T> Clone for EntryRef<T> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user