Wasm: move WasmModule definition to mod.rs

This commit is contained in:
Brian Carroll 2022-01-08 15:29:13 +00:00
parent d88b86e884
commit b8ab6af203
3 changed files with 104 additions and 97 deletions

View file

@ -6,4 +6,103 @@ pub mod serialize;
pub use code_builder::{Align, CodeBuilder, LocalId, ValueType, VmSymbolState};
pub use linking::SymInfo;
pub use sections::{ConstExpr, Export, ExportType, Global, GlobalType, Signature, WasmModule};
pub use sections::{ConstExpr, Export, ExportType, Global, GlobalType, Signature};
use self::linking::{LinkingSection, RelocationSection};
use self::sections::{
CodeSection, DataSection, ExportSection, FunctionSection, GlobalSection, ImportSection,
MemorySection, OpaqueSection, TypeSection,
};
use self::serialize::{SerialBuffer, Serialize};
#[derive(Debug)]
pub struct WasmModule<'a> {
pub types: TypeSection<'a>,
pub import: ImportSection<'a>,
pub function: FunctionSection<'a>,
pub table: OpaqueSection<'a>,
pub memory: MemorySection,
pub global: GlobalSection<'a>,
pub export: ExportSection<'a>,
pub start: OpaqueSection<'a>,
pub element: OpaqueSection<'a>,
pub code: CodeSection<'a>,
pub data: DataSection<'a>,
pub linking: LinkingSection<'a>,
pub relocations: RelocationSection<'a>,
}
impl<'a> WasmModule<'a> {
pub const WASM_VERSION: u32 = 1;
/// Create entries in the Type and Function sections for a function signature
pub fn add_function_signature(&mut self, signature: Signature<'a>) {
let index = self.types.insert(signature);
self.function.add_sig(index);
}
/// Serialize the module to bytes
/// (Mutates some data related to linking)
pub fn serialize_mut<T: SerialBuffer>(&mut self, buffer: &mut T) {
buffer.append_u8(0);
buffer.append_slice("asm".as_bytes());
buffer.write_unencoded_u32(Self::WASM_VERSION);
// Keep track of (non-empty) section indices for linking
let mut counter = SectionCounter {
buffer_size: buffer.size(),
section_index: 0,
};
counter.serialize_and_count(buffer, &self.types);
counter.serialize_and_count(buffer, &self.import);
counter.serialize_and_count(buffer, &self.function);
counter.serialize_and_count(buffer, &self.table);
counter.serialize_and_count(buffer, &self.memory);
counter.serialize_and_count(buffer, &self.global);
counter.serialize_and_count(buffer, &self.export);
counter.serialize_and_count(buffer, &self.start);
counter.serialize_and_count(buffer, &self.element);
// Code section is the only one with relocations so we can stop counting
let code_section_index = counter.section_index;
self.code
.serialize_with_relocs(buffer, &mut self.relocations.entries);
self.data.serialize(buffer);
self.linking.serialize(buffer);
self.relocations.target_section_index = Some(code_section_index);
self.relocations.serialize(buffer);
}
}
/// Helper struct to count non-empty sections.
/// Needed to generate linking data, which refers to target sections by index.
struct SectionCounter {
buffer_size: usize,
section_index: u32,
}
impl SectionCounter {
/// Update the section counter if buffer size increased since last call
#[inline]
fn update<SB: SerialBuffer>(&mut self, buffer: &mut SB) {
let new_size = buffer.size();
if new_size > self.buffer_size {
self.section_index += 1;
self.buffer_size = new_size;
}
}
#[inline]
fn serialize_and_count<SB: SerialBuffer, S: Serialize>(
&mut self,
buffer: &mut SB,
section: &S,
) {
section.serialize(buffer);
self.update(buffer);
}
}