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

@ -23,11 +23,11 @@ use crate::wasm_module::linking::{
};
use crate::wasm_module::sections::{
CodeSection, DataMode, DataSection, DataSegment, ExportSection, FunctionSection, GlobalSection,
Import, ImportDesc, ImportSection, MemorySection, OpaqueSection, TypeSection, WasmModule,
Import, ImportDesc, ImportSection, MemorySection, OpaqueSection, TypeSection,
};
use crate::wasm_module::{
code_builder, CodeBuilder, ConstExpr, Export, ExportType, Global, GlobalType, LocalId,
Signature, SymInfo, ValueType,
Signature, SymInfo, ValueType, WasmModule,
};
use crate::{
copy_memory, round_up_to_alignment, CopyMemoryConfig, Env, BUILTINS_IMPORT_MODULE_NAME,

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);
}
}

View file

@ -1,7 +1,7 @@
use bumpalo::collections::vec::Vec;
use bumpalo::Bump;
use super::linking::{LinkingSection, RelocationEntry, RelocationSection};
use super::linking::RelocationEntry;
use super::opcodes::OpCode;
use super::serialize::{decode_u32_or_panic, SerialBuffer, Serialize};
use super::{CodeBuilder, ValueType};
@ -328,7 +328,7 @@ impl<'a> FunctionSection<'a> {
}
}
fn add_sig(&mut self, sig_id: u32) {
pub(super) fn add_sig(&mut self, sig_id: u32) {
self.bytes.encode_u32(sig_id);
self.count += 1;
}
@ -639,35 +639,6 @@ impl Serialize for DataSection<'_> {
*
*******************************************************************/
/// 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);
}
}
/// A Wasm module section that we don't use for Roc code,
/// but may be present in a preloaded binary
#[derive(Debug, Default)]
@ -689,69 +660,6 @@ impl Serialize for OpaqueSection<'_> {
}
}
#[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);
}
}
#[cfg(test)]
mod tests {
use super::*;