mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 22:34:45 +00:00
Move WasmModule initialisation into WasmBackend
It helps to coordinate different sections with related values, based on knowledge of Roc rather than Wasm.
This commit is contained in:
parent
1b91fd9533
commit
414c9e6f86
3 changed files with 58 additions and 49 deletions
|
@ -9,8 +9,14 @@ use roc_mono::layout::Layout;
|
||||||
|
|
||||||
use crate::layout::WasmLayout;
|
use crate::layout::WasmLayout;
|
||||||
use crate::storage::{Storage, StoredValue, StoredValueKind};
|
use crate::storage::{Storage, StoredValue, StoredValueKind};
|
||||||
|
use crate::wasm_module::linking::{LinkingSection, RelocationSection};
|
||||||
|
use crate::wasm_module::sections::{
|
||||||
|
CodeSection, DataMode, DataSection, DataSegment, ExportSection, FunctionSection, GlobalSection,
|
||||||
|
ImportSection, MemorySection, TypeSection, WasmModule,
|
||||||
|
};
|
||||||
use crate::wasm_module::{
|
use crate::wasm_module::{
|
||||||
code_builder, BlockType, CodeBuilder, LocalId, Signature, ValueType, WasmModule,
|
code_builder, BlockType, CodeBuilder, ConstExpr, Export, ExportType, Global, GlobalType,
|
||||||
|
LocalId, Signature, ValueType,
|
||||||
};
|
};
|
||||||
use crate::{copy_memory, CopyMemoryConfig, Env, PTR_TYPE};
|
use crate::{copy_memory, CopyMemoryConfig, Env, PTR_TYPE};
|
||||||
|
|
||||||
|
@ -18,16 +24,12 @@ use crate::{copy_memory, CopyMemoryConfig, Env, PTR_TYPE};
|
||||||
// Follow Emscripten's example by using 1kB (4 bytes would probably do)
|
// Follow Emscripten's example by using 1kB (4 bytes would probably do)
|
||||||
const UNUSED_DATA_SECTION_BYTES: u32 = 1024;
|
const UNUSED_DATA_SECTION_BYTES: u32 = 1024;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
struct LabelId(u32);
|
|
||||||
|
|
||||||
pub struct WasmBackend<'a> {
|
pub struct WasmBackend<'a> {
|
||||||
env: &'a Env<'a>,
|
env: &'a Env<'a>,
|
||||||
|
|
||||||
// Module-level data
|
// Module-level data
|
||||||
pub module: WasmModule<'a>,
|
pub module: WasmModule<'a>,
|
||||||
_data_offset_map: MutMap<Literal<'a>, u32>,
|
next_literal_addr: u32,
|
||||||
_data_offset_next: u32,
|
|
||||||
proc_symbols: Vec<'a, Symbol>,
|
proc_symbols: Vec<'a, Symbol>,
|
||||||
|
|
||||||
// Function-level data
|
// Function-level data
|
||||||
|
@ -41,13 +43,54 @@ pub struct WasmBackend<'a> {
|
||||||
|
|
||||||
impl<'a> WasmBackend<'a> {
|
impl<'a> WasmBackend<'a> {
|
||||||
pub fn new(env: &'a Env<'a>, proc_symbols: Vec<'a, Symbol>) -> Self {
|
pub fn new(env: &'a Env<'a>, proc_symbols: Vec<'a, Symbol>) -> Self {
|
||||||
|
const MEMORY_INIT_SIZE: u32 = 1024 * 1024;
|
||||||
|
|
||||||
|
let mut module = WasmModule {
|
||||||
|
types: TypeSection::new(env.arena),
|
||||||
|
import: ImportSection::new(env.arena),
|
||||||
|
function: FunctionSection::new(env.arena),
|
||||||
|
table: (), // Unused in Roc (mainly for function pointers)
|
||||||
|
memory: MemorySection::new(MEMORY_INIT_SIZE),
|
||||||
|
global: GlobalSection::new(env.arena),
|
||||||
|
export: ExportSection::new(env.arena),
|
||||||
|
start: (), // Entry function. In Roc this would be part of the platform.
|
||||||
|
element: (), // Unused in Roc (related to table section)
|
||||||
|
code: CodeSection::new(env.arena),
|
||||||
|
data: DataSection::new(env.arena),
|
||||||
|
linking: LinkingSection::new(env.arena),
|
||||||
|
reloc_code: RelocationSection::new(env.arena, "reloc.CODE"),
|
||||||
|
reloc_data: RelocationSection::new(env.arena, "reloc.DATA"),
|
||||||
|
};
|
||||||
|
|
||||||
|
module.export.entries.push(Export {
|
||||||
|
name: "memory".to_string(),
|
||||||
|
ty: ExportType::Mem,
|
||||||
|
index: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
let stack_pointer_global = Global {
|
||||||
|
ty: GlobalType {
|
||||||
|
value_type: ValueType::I32,
|
||||||
|
is_mutable: true,
|
||||||
|
},
|
||||||
|
init: ConstExpr::I32(MEMORY_INIT_SIZE as i32),
|
||||||
|
};
|
||||||
|
module.global.entries.push(stack_pointer_global);
|
||||||
|
|
||||||
|
let literal_segment = DataSegment {
|
||||||
|
mode: DataMode::Active {
|
||||||
|
offset: ConstExpr::I32(UNUSED_DATA_SECTION_BYTES as i32),
|
||||||
|
},
|
||||||
|
init: Vec::with_capacity_in(64, env.arena),
|
||||||
|
};
|
||||||
|
module.data.segments.push(literal_segment);
|
||||||
|
|
||||||
WasmBackend {
|
WasmBackend {
|
||||||
env,
|
env,
|
||||||
|
|
||||||
// Module-level data
|
// Module-level data
|
||||||
module: WasmModule::new(env.arena),
|
module,
|
||||||
_data_offset_map: MutMap::default(),
|
next_literal_addr: UNUSED_DATA_SECTION_BYTES,
|
||||||
_data_offset_next: UNUSED_DATA_SECTION_BYTES,
|
|
||||||
proc_symbols,
|
proc_symbols,
|
||||||
|
|
||||||
// Function-level data
|
// Function-level data
|
||||||
|
|
|
@ -13,8 +13,8 @@ use roc_mono::layout::LayoutIds;
|
||||||
|
|
||||||
use crate::backend::WasmBackend;
|
use crate::backend::WasmBackend;
|
||||||
use crate::wasm_module::{
|
use crate::wasm_module::{
|
||||||
Align, CodeBuilder, Export, ExportType, Global, ConstExpr, GlobalType, LinkingSubSection,
|
Align, CodeBuilder, Export, ExportType, LinkingSubSection, LocalId, SymInfo, ValueType,
|
||||||
LocalId, SymInfo, ValueType, WasmModule,
|
WasmModule,
|
||||||
};
|
};
|
||||||
|
|
||||||
const PTR_SIZE: u32 = 4;
|
const PTR_SIZE: u32 = 4;
|
||||||
|
@ -73,21 +73,6 @@ pub fn build_module_help<'a>(
|
||||||
let symbol_table = LinkingSubSection::SymbolTable(symbol_table_entries);
|
let symbol_table = LinkingSubSection::SymbolTable(symbol_table_entries);
|
||||||
backend.module.linking.subsections.push(symbol_table);
|
backend.module.linking.subsections.push(symbol_table);
|
||||||
|
|
||||||
backend.module.export.entries.push(Export {
|
|
||||||
name: "memory".to_string(),
|
|
||||||
ty: ExportType::Mem,
|
|
||||||
index: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
let stack_pointer_init = backend.module.memory.min_size().unwrap() as i32;
|
|
||||||
backend.module.global.entries.push(Global {
|
|
||||||
ty: GlobalType {
|
|
||||||
value_type: ValueType::I32,
|
|
||||||
is_mutable: true,
|
|
||||||
},
|
|
||||||
init: ConstExpr::I32(stack_pointer_init),
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(backend.module)
|
Ok(backend.module)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -351,6 +351,7 @@ impl Serialize for ConstExpr {
|
||||||
buffer.encode_f64(*x);
|
buffer.encode_f64(*x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
buffer.append_u8(opcodes::END);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,7 +366,6 @@ impl Serialize for Global {
|
||||||
fn serialize<T: SerialBuffer>(&self, buffer: &mut T) {
|
fn serialize<T: SerialBuffer>(&self, buffer: &mut T) {
|
||||||
self.ty.serialize(buffer);
|
self.ty.serialize(buffer);
|
||||||
self.init.serialize(buffer);
|
self.init.serialize(buffer);
|
||||||
buffer.append_u8(opcodes::END);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,8 +482,8 @@ pub enum DataMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DataSegment<'a> {
|
pub struct DataSegment<'a> {
|
||||||
mode: DataMode,
|
pub mode: DataMode,
|
||||||
init: Vec<'a, u8>,
|
pub init: Vec<'a, u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialize for DataSegment<'_> {
|
impl Serialize for DataSegment<'_> {
|
||||||
|
@ -503,7 +503,7 @@ impl Serialize for DataSegment<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DataSection<'a> {
|
pub struct DataSection<'a> {
|
||||||
segments: Vec<'a, DataSegment<'a>>,
|
pub segments: Vec<'a, DataSegment<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DataSection<'a> {
|
impl<'a> DataSection<'a> {
|
||||||
|
@ -557,25 +557,6 @@ pub struct WasmModule<'a> {
|
||||||
impl<'a> WasmModule<'a> {
|
impl<'a> WasmModule<'a> {
|
||||||
pub const WASM_VERSION: u32 = 1;
|
pub const WASM_VERSION: u32 = 1;
|
||||||
|
|
||||||
pub fn new(arena: &'a Bump) -> Self {
|
|
||||||
WasmModule {
|
|
||||||
types: TypeSection::new(arena),
|
|
||||||
import: ImportSection::new(arena),
|
|
||||||
function: FunctionSection::new(arena),
|
|
||||||
table: (), // Unused in Roc (mainly for function pointers)
|
|
||||||
memory: MemorySection::new(1024 * 1024),
|
|
||||||
global: GlobalSection::new(arena),
|
|
||||||
export: ExportSection::new(arena),
|
|
||||||
start: (), // Entry function. In Roc this would be part of the platform.
|
|
||||||
element: (), // Unused in Roc (related to table section)
|
|
||||||
code: CodeSection::new(arena),
|
|
||||||
data: DataSection::new(arena),
|
|
||||||
linking: LinkingSection::new(arena),
|
|
||||||
reloc_code: RelocationSection::new(arena, "reloc.CODE"),
|
|
||||||
reloc_data: RelocationSection::new(arena, "reloc.DATA"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create entries in the Type and Function sections for a function signature
|
/// Create entries in the Type and Function sections for a function signature
|
||||||
pub fn add_function_signature(&mut self, signature: Signature<'a>) {
|
pub fn add_function_signature(&mut self, signature: Signature<'a>) {
|
||||||
let index = self.types.insert(signature);
|
let index = self.types.insert(signature);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue