diff --git a/compiler/gen_wasm/src/backend.rs b/compiler/gen_wasm/src/backend.rs index e7e39531e4..c1b34873a8 100644 --- a/compiler/gen_wasm/src/backend.rs +++ b/compiler/gen_wasm/src/backend.rs @@ -40,7 +40,8 @@ pub struct WasmBackend<'a> { module: WasmModule<'a>, layout_ids: LayoutIds<'a>, next_constant_addr: u32, - preloaded_fn_index_map: MutMap<&'a str, u32>, + fn_index_offset: u32, + preloaded_functions_map: MutMap<&'a [u8], u32>, proc_symbols: Vec<'a, (Symbol, u32)>, helper_proc_gen: CodeGenHelp<'a>, @@ -62,6 +63,8 @@ impl<'a> WasmBackend<'a> { layout_ids: LayoutIds<'a>, proc_symbols: Vec<'a, (Symbol, u32)>, module: WasmModule<'a>, + fn_index_offset: u32, + preloaded_functions_map: MutMap<&'a [u8], u32>, helper_proc_gen: CodeGenHelp<'a>, ) -> Self { WasmBackend { @@ -73,7 +76,8 @@ impl<'a> WasmBackend<'a> { layout_ids, next_constant_addr: CONST_SEGMENT_BASE_ADDR, - preloaded_fn_index_map: MutMap::default(), + fn_index_offset, + preloaded_functions_map, proc_symbols, helper_proc_gen, @@ -542,8 +546,7 @@ impl<'a> WasmBackend<'a> { for (roc_proc_index, (ir_sym, linker_sym_index)) in self.proc_symbols.iter().enumerate() { - let wasm_fn_index = - self.module.code.preloaded_count + roc_proc_index as u32; + let wasm_fn_index = self.fn_index_offset + roc_proc_index as u32; if ir_sym == func_sym { let num_wasm_args = param_types.len(); let has_return_val = ret_type.is_some(); @@ -1461,7 +1464,7 @@ impl<'a> WasmBackend<'a> { ) { let num_wasm_args = param_types.len(); let has_return_val = ret_type.is_some(); - let fn_index = self.preloaded_fn_index_map[name]; + let fn_index = self.preloaded_functions_map[name.as_bytes()]; let linker_symbol_index = u32::MAX; self.code_builder diff --git a/compiler/gen_wasm/src/lib.rs b/compiler/gen_wasm/src/lib.rs index b718ff9f43..6996b2a13b 100644 --- a/compiler/gen_wasm/src/lib.rs +++ b/compiler/gen_wasm/src/lib.rs @@ -92,8 +92,17 @@ pub fn build_module_help<'a>( fn_index += 1; } + // Pre-load the WasmModule with data from the platform & builtins object file let initial_module = WasmModule::preload(env.arena, preload_bytes); - let main_function_index = maybe_main_fn_index.unwrap() + initial_module.code.preloaded_count; + + // Adjust Wasm function indices to account for functions from the object file + let runtime_import_fn_count: u32 = initial_module.import.function_count(); // to be imported at runtime (e.g. WASI) + let fn_index_offset: u32 = runtime_import_fn_count + initial_module.code.preloaded_count; + + // Get a map of name to index for the preloaded functions + // Assumes the preloaded object file has all symbols exported, as per `zig build-lib -dymamic` + let preloaded_functions_map: MutMap<&'a [u8], u32> = + initial_module.export.function_index_map(env.arena); let mut backend = WasmBackend::new( env, @@ -101,6 +110,8 @@ pub fn build_module_help<'a>( layout_ids, proc_symbols, initial_module, + fn_index_offset, + preloaded_functions_map, CodeGenHelp::new(env.arena, IntWidth::I32, env.module_id), ); @@ -137,6 +148,7 @@ pub fn build_module_help<'a>( let module = backend.into_module(); + let main_function_index = maybe_main_fn_index.unwrap() + fn_index_offset; Ok((module, main_function_index)) }