wasmer_compiler/engine/
resolver.rs1use crate::LinkError;
4use more_asserts::assert_ge;
5use wasmer_types::entity::{BoxedSlice, EntityRef, PrimaryMap};
6use wasmer_types::{
7 ExternType, FunctionIndex, ImportError, ImportIndex, MemoryIndex, ModuleInfo, TableIndex,
8};
9
10use wasmer_vm::{
11 FunctionBodyPtr, Imports, LinearMemory, MemoryStyle, StoreObjects, TableStyle, VMExtern,
12 VMFunctionBody, VMFunctionImport, VMFunctionKind, VMGlobalImport, VMMemoryImport,
13 VMTableImport,
14};
15
16fn get_extern_from_import(module: &ModuleInfo, import_index: &ImportIndex) -> ExternType {
18 match import_index {
19 ImportIndex::Function(index) => {
20 let func = module.signatures[module.functions[*index]].clone();
21 ExternType::Function(func)
22 }
23 ImportIndex::Table(index) => {
24 let table = module.tables[*index];
25 ExternType::Table(table)
26 }
27 ImportIndex::Memory(index) => {
28 let memory = module.memories[*index];
29 ExternType::Memory(memory)
30 }
31 ImportIndex::Global(index) => {
32 let global = module.globals[*index];
33 ExternType::Global(global)
34 }
35 }
36}
37
38fn get_extern_type(context: &StoreObjects, extern_: &VMExtern) -> ExternType {
40 match extern_ {
41 VMExtern::Function(f) => ExternType::Function(f.get(context).signature.clone()),
42 VMExtern::Table(t) => ExternType::Table(*t.get(context).ty()),
43 VMExtern::Memory(m) => ExternType::Memory(m.get(context).ty()),
44 VMExtern::Global(g) => {
45 let global = g.get(context).ty();
46 ExternType::Global(*global)
47 }
48 }
49}
50
51fn get_runtime_size(context: &StoreObjects, extern_: &VMExtern) -> Option<u32> {
52 match extern_ {
53 VMExtern::Table(t) => Some(t.get(context).get_runtime_size()),
54 VMExtern::Memory(m) => Some(m.get(context).get_runtime_size()),
55 _ => None,
56 }
57}
58
59#[allow(clippy::result_large_err)]
64pub fn resolve_imports(
65 module: &ModuleInfo,
66 imports: &[VMExtern],
67 context: &mut StoreObjects,
68 finished_dynamic_function_trampolines: &BoxedSlice<FunctionIndex, FunctionBodyPtr>,
69 memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
70 _table_styles: &PrimaryMap<TableIndex, TableStyle>,
71) -> Result<Imports, LinkError> {
72 let mut function_imports = PrimaryMap::with_capacity(module.num_imported_functions);
73 let mut table_imports = PrimaryMap::with_capacity(module.num_imported_tables);
74 let mut memory_imports = PrimaryMap::with_capacity(module.num_imported_memories);
75 let mut global_imports = PrimaryMap::with_capacity(module.num_imported_globals);
76
77 for (
78 wasmer_types::ImportKey {
79 module: module_name,
80 field,
81 import_idx,
82 },
83 import_index,
84 ) in module.imports.iter()
85 {
86 let import_extern = get_extern_from_import(module, import_index);
87 let resolved = if let Some(r) = imports.get(*import_idx as usize) {
88 r
89 } else {
90 return Err(LinkError::Import(
91 module_name.to_string(),
92 field.to_string(),
93 ImportError::UnknownImport(import_extern),
94 ));
95 };
96 let extern_type = get_extern_type(context, resolved);
97 let runtime_size = get_runtime_size(context, resolved);
98 if !extern_type.is_compatible_with(&import_extern, runtime_size) {
99 return Err(LinkError::Import(
100 module_name.to_string(),
101 field.to_string(),
102 ImportError::IncompatibleType(import_extern, extern_type),
103 ));
104 }
105 match *resolved {
106 VMExtern::Function(handle) => {
107 let f = handle.get_mut(context);
108 let address = match f.kind {
109 VMFunctionKind::Dynamic => {
110 let index = FunctionIndex::new(function_imports.len());
114 let ptr = finished_dynamic_function_trampolines[index].0
115 as *mut VMFunctionBody as _;
116 unsafe { f.anyfunc.as_ptr().as_mut() }.func_ptr = ptr;
122 ptr
123 }
124 VMFunctionKind::Static => unsafe { f.anyfunc.as_ptr().as_ref().func_ptr },
125 };
126
127 function_imports.push(VMFunctionImport {
128 body: address,
129 environment: unsafe { f.anyfunc.as_ptr().as_ref().vmctx },
130 handle,
131 });
132 }
133 VMExtern::Table(handle) => {
134 let t = handle.get(context);
135 match import_index {
136 ImportIndex::Table(index) => {
137 let import_table_ty = t.ty();
138 let expected_table_ty = &module.tables[*index];
139 if import_table_ty.ty != expected_table_ty.ty {
140 return Err(LinkError::Import(
141 module_name.to_string(),
142 field.to_string(),
143 ImportError::IncompatibleType(import_extern, extern_type),
144 ));
145 }
146
147 table_imports.push(VMTableImport {
148 definition: t.vmtable(),
149 handle,
150 });
151 }
152 _ => {
153 unreachable!("Table resolution did not match");
154 }
155 }
156 }
157 VMExtern::Memory(handle) => {
158 let m = handle.get(context);
159 match import_index {
160 ImportIndex::Memory(index) => {
161 let export_memory_style = m.style();
164 let import_memory_style = &memory_styles[*index];
165 if let (
166 MemoryStyle::Static { bound, .. },
167 MemoryStyle::Static {
168 bound: import_bound,
169 ..
170 },
171 ) = (export_memory_style, &import_memory_style)
172 {
173 assert_ge!(bound, *import_bound);
174 }
175 assert_ge!(
176 export_memory_style.offset_guard_size(),
177 import_memory_style.offset_guard_size()
178 );
179 }
180 _ => {
181 panic!("Memory resolution didn't matched");
184 }
185 }
186
187 memory_imports.push(VMMemoryImport {
188 definition: m.vmmemory(),
189 handle,
190 });
191 }
192
193 VMExtern::Global(handle) => {
194 let g = handle.get(context);
195 global_imports.push(VMGlobalImport {
196 definition: g.vmglobal(),
197 handle,
198 });
199 }
200 }
201 }
202
203 Ok(Imports::new(
204 function_imports,
205 table_imports,
206 memory_imports,
207 global_imports,
208 ))
209}