diff --git a/compiler/gen_wasm/src/backend.rs b/compiler/gen_wasm/src/backend.rs index 80ffe09d6e..762b6b81ee 100644 --- a/compiler/gen_wasm/src/backend.rs +++ b/compiler/gen_wasm/src/backend.rs @@ -9,8 +9,14 @@ use roc_mono::layout::Layout; use crate::layout::WasmLayout; 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::{ - 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}; @@ -18,16 +24,12 @@ use crate::{copy_memory, CopyMemoryConfig, Env, PTR_TYPE}; // Follow Emscripten's example by using 1kB (4 bytes would probably do) const UNUSED_DATA_SECTION_BYTES: u32 = 1024; -#[derive(Clone, Copy, Debug)] -struct LabelId(u32); - pub struct WasmBackend<'a> { env: &'a Env<'a>, // Module-level data pub module: WasmModule<'a>, - _data_offset_map: MutMap, u32>, - _data_offset_next: u32, + next_literal_addr: u32, proc_symbols: Vec<'a, Symbol>, // Function-level data @@ -41,13 +43,54 @@ pub struct WasmBackend<'a> { impl<'a> WasmBackend<'a> { 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 { env, // Module-level data - module: WasmModule::new(env.arena), - _data_offset_map: MutMap::default(), - _data_offset_next: UNUSED_DATA_SECTION_BYTES, + module, + next_literal_addr: UNUSED_DATA_SECTION_BYTES, proc_symbols, // Function-level data diff --git a/compiler/gen_wasm/src/lib.rs b/compiler/gen_wasm/src/lib.rs index 487ed3f3b7..433e098247 100644 --- a/compiler/gen_wasm/src/lib.rs +++ b/compiler/gen_wasm/src/lib.rs @@ -13,8 +13,8 @@ use roc_mono::layout::LayoutIds; use crate::backend::WasmBackend; use crate::wasm_module::{ - Align, CodeBuilder, Export, ExportType, Global, ConstExpr, GlobalType, LinkingSubSection, - LocalId, SymInfo, ValueType, WasmModule, + Align, CodeBuilder, Export, ExportType, LinkingSubSection, LocalId, SymInfo, ValueType, + WasmModule, }; const PTR_SIZE: u32 = 4; @@ -73,21 +73,6 @@ pub fn build_module_help<'a>( let symbol_table = LinkingSubSection::SymbolTable(symbol_table_entries); 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) } diff --git a/compiler/gen_wasm/src/wasm_module/sections.rs b/compiler/gen_wasm/src/wasm_module/sections.rs index 65ab5eea7a..27f8d8ff45 100644 --- a/compiler/gen_wasm/src/wasm_module/sections.rs +++ b/compiler/gen_wasm/src/wasm_module/sections.rs @@ -351,6 +351,7 @@ impl Serialize for ConstExpr { buffer.encode_f64(*x); } } + buffer.append_u8(opcodes::END); } } @@ -365,7 +366,6 @@ impl Serialize for Global { fn serialize(&self, buffer: &mut T) { self.ty.serialize(buffer); self.init.serialize(buffer); - buffer.append_u8(opcodes::END); } } @@ -482,8 +482,8 @@ pub enum DataMode { } pub struct DataSegment<'a> { - mode: DataMode, - init: Vec<'a, u8>, + pub mode: DataMode, + pub init: Vec<'a, u8>, } impl Serialize for DataSegment<'_> { @@ -503,7 +503,7 @@ impl Serialize for DataSegment<'_> { } pub struct DataSection<'a> { - segments: Vec<'a, DataSegment<'a>>, + pub segments: Vec<'a, DataSegment<'a>>, } impl<'a> DataSection<'a> { @@ -557,25 +557,6 @@ pub struct WasmModule<'a> { impl<'a> WasmModule<'a> { 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 pub fn add_function_signature(&mut self, signature: Signature<'a>) { let index = self.types.insert(signature);