(&self, store: &mut crate::Store, module: &Module)
| 212 | } |
| 213 | |
| 214 | pub(crate) fn link(&self, store: &mut crate::Store, module: &Module) -> Result<ResolvedImports> { |
| 215 | let (global_count, table_count, mem_count, func_count) = |
| 216 | module.imports.iter().fold((0, 0, 0, 0), |(g, t, m, f), import| match import.kind { |
| 217 | ImportKind::Global(_) => (g + 1, t, m, f), |
| 218 | ImportKind::Table(_) => (g, t + 1, m, f), |
| 219 | ImportKind::Memory(_) => (g, t, m + 1, f), |
| 220 | ImportKind::Function(_) => (g, t, m, f + 1), |
| 221 | }); |
| 222 | |
| 223 | let mut imports = ResolvedImports { |
| 224 | globals: Vec::with_capacity(global_count + module.globals.len()), |
| 225 | tables: Vec::with_capacity(table_count + module.table_types.len()), |
| 226 | memories: Vec::with_capacity(mem_count + module.memory_types.len()), |
| 227 | funcs: Vec::with_capacity(func_count + module.funcs.len()), |
| 228 | }; |
| 229 | |
| 230 | for import in &*module.imports { |
| 231 | if let Some(defined) = self.take_defined(import) { |
| 232 | match defined { |
| 233 | Extern::Global(global) => { |
| 234 | let ImportKind::Global(import_ty) = &import.kind else { |
| 235 | cold_path(); |
| 236 | return Err(LinkingError::incompatible_import_type(import).into()); |
| 237 | }; |
| 238 | let global_instance = store.state.get_global(global.0.addr); |
| 239 | Self::compare_types(import, &global_instance.ty, import_ty)?; |
| 240 | imports.globals.push(global.0.addr); |
| 241 | } |
| 242 | Extern::Table(table) => { |
| 243 | let ImportKind::Table(import_ty) = &import.kind else { |
| 244 | cold_path(); |
| 245 | return Err(LinkingError::incompatible_import_type(import).into()); |
| 246 | }; |
| 247 | let table_instance = store.state.get_table(table.0.addr); |
| 248 | let mut kind = table_instance.kind.clone(); |
| 249 | kind.size_initial = table_instance.size() as u32; |
| 250 | Self::compare_table_types(import, &kind, import_ty)?; |
| 251 | imports.tables.push(table.0.addr); |
| 252 | } |
| 253 | Extern::Memory(memory) => { |
| 254 | let ImportKind::Memory(import_ty) = &import.kind else { |
| 255 | cold_path(); |
| 256 | return Err(LinkingError::incompatible_import_type(import).into()); |
| 257 | }; |
| 258 | let mem = store.state.get_mem(memory.0.addr); |
| 259 | Self::compare_memory_types(import, &mem.kind, import_ty, mem.page_count)?; |
| 260 | imports.memories.push(memory.0.addr); |
| 261 | } |
| 262 | Extern::Function(func_handle) => { |
| 263 | let ImportKind::Function(ty) = &import.kind else { |
| 264 | cold_path(); |
| 265 | return Err(LinkingError::incompatible_import_type(import).into()); |
| 266 | }; |
| 267 | let import_func_type = module |
| 268 | .func_types |
| 269 | .get(*ty as usize) |
| 270 | .ok_or_else(|| LinkingError::incompatible_import_type(import))?; |
| 271 | func_handle.item.validate_store(store)?; |
no test coverage detected