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::{
|
use crate::wasm_module::sections::{
|
||||||
CodeSection, DataMode, DataSection, DataSegment, ExportSection, FunctionSection, GlobalSection,
|
CodeSection, DataMode, DataSection, DataSegment, ExportSection, FunctionSection, GlobalSection,
|
||||||
Import, ImportDesc, ImportSection, MemorySection, OpaqueSection, TypeSection, WasmModule,
|
Import, ImportDesc, ImportSection, MemorySection, OpaqueSection, TypeSection,
|
||||||
};
|
};
|
||||||
use crate::wasm_module::{
|
use crate::wasm_module::{
|
||||||
code_builder, CodeBuilder, ConstExpr, Export, ExportType, Global, GlobalType, LocalId,
|
code_builder, CodeBuilder, ConstExpr, Export, ExportType, Global, GlobalType, LocalId,
|
||||||
Signature, SymInfo, ValueType,
|
Signature, SymInfo, ValueType, WasmModule,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
copy_memory, round_up_to_alignment, CopyMemoryConfig, Env, BUILTINS_IMPORT_MODULE_NAME,
|
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 code_builder::{Align, CodeBuilder, LocalId, ValueType, VmSymbolState};
|
||||||
pub use linking::SymInfo;
|
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::collections::vec::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
|
||||||
use super::linking::{LinkingSection, RelocationEntry, RelocationSection};
|
use super::linking::RelocationEntry;
|
||||||
use super::opcodes::OpCode;
|
use super::opcodes::OpCode;
|
||||||
use super::serialize::{decode_u32_or_panic, SerialBuffer, Serialize};
|
use super::serialize::{decode_u32_or_panic, SerialBuffer, Serialize};
|
||||||
use super::{CodeBuilder, ValueType};
|
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.bytes.encode_u32(sig_id);
|
||||||
self.count += 1;
|
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,
|
/// A Wasm module section that we don't use for Roc code,
|
||||||
/// but may be present in a preloaded binary
|
/// but may be present in a preloaded binary
|
||||||
#[derive(Debug, Default)]
|
#[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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue