mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Wasm: move WasmModule definition to mod.rs
This commit is contained in:
parent
d88b86e884
commit
b8ab6af203
3 changed files with 104 additions and 97 deletions
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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::*;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue