use crate::info::{Module, ModuleContext};
use crate::stack_ext::StackExt;
use wasm_encoder::SectionId;
pub(crate) fn instrument(cx: &ModuleContext<'_>) -> Vec<u8> {
log::debug!("Instrumenting the input Wasm");
struct StackEntry<'a> {
module: Module,
encoder: wasm_encoder::Module,
sections: std::slice::Iter<'a, wasm_encoder::RawSection<'a>>,
}
let root = cx.root();
let mut stack = vec![StackEntry {
module: root,
encoder: wasm_encoder::Module::new(),
sections: root.raw_sections(cx).iter(),
}];
loop {
assert!(!stack.is_empty());
match stack.top_mut().sections.next() {
Some(section) if section.id == u8::from(SectionId::Export) => {
let entry = stack.top_mut();
let mut exports = wasm_encoder::ExportSection::new();
for export in entry.module.exports(cx) {
exports.export(
export.name,
match export.kind {
wasmparser::ExternalKind::Func => wasm_encoder::ExportKind::Func,
wasmparser::ExternalKind::Table => wasm_encoder::ExportKind::Table,
wasmparser::ExternalKind::Memory => wasm_encoder::ExportKind::Memory,
wasmparser::ExternalKind::Global => wasm_encoder::ExportKind::Global,
wasmparser::ExternalKind::Tag => {
unreachable!("should have been rejected in validation/parsing")
}
},
export.index,
);
}
for (i, (j, _)) in entry.module.defined_globals(cx).enumerate() {
let name = format!("__wizer_global_{}", i);
exports.export(&name, wasm_encoder::ExportKind::Global, j);
}
for (i, (j, _)) in entry.module.defined_memories(cx).enumerate() {
let name = format!("__wizer_memory_{}", i);
exports.export(&name, wasm_encoder::ExportKind::Memory, j);
}
entry.encoder.section(&exports);
}
None => {
let entry = stack.pop().unwrap();
if entry.module.is_root() {
assert!(stack.is_empty());
return entry.encoder.finish();
}
}
Some(section) => {
stack.top_mut().encoder.section(section);
}
}
}
}