@@ -6,9 +6,8 @@ use anyhow::{Context, Result};
6
6
use indexmap:: { IndexMap , IndexSet } ;
7
7
use std:: borrow:: Cow ;
8
8
use std:: collections:: { HashMap , HashSet } ;
9
- use wasmparser:: FuncType ;
10
9
use wit_parser:: {
11
- abi:: { AbiVariant , WasmSignature , WasmType } ,
10
+ abi:: { AbiVariant , WasmSignature } ,
12
11
Function , InterfaceId , LiveTypes , Resolve , TypeDefKind , TypeId , TypeOwner , WorldId , WorldItem ,
13
12
WorldKey ,
14
13
} ;
@@ -130,12 +129,51 @@ impl<'a> ComponentWorld<'a> {
130
129
let wasm = if library_info. is_some ( ) {
131
130
Cow :: Borrowed ( wasm as & [ u8 ] )
132
131
} else {
133
- let required = self . required_adapter_exports (
132
+ // Without `library_info` this means that this is an adapter.
133
+ // The goal of the adapter is to provide a suite of symbols that
134
+ // can be imported, but not all symbols may be imported. Here
135
+ // the module is trimmed down to only what's needed by the
136
+ // original main module.
137
+ //
138
+ // The main module requires `required_by_import` above, but
139
+ // adapters may themselves also export WIT items. To handle this
140
+ // the sequence of operations here are:
141
+ //
142
+ // 1. First the adapter is validated as-is. This ensures that
143
+ // everything looks good before GC.
144
+ // 2. The metadata from step (1) is used to determine the set of
145
+ // WIT-level exports that are needed. This includes things
146
+ // like realloc functions and such.
147
+ // 3. The set of WIT-level functions from (2) is unioned with
148
+ // `required_by_import` to create the set of required exports
149
+ // of the adapter.
150
+ // 4. This set of exports is used to delete some exports of the
151
+ // adapter and then perform a GC pass.
152
+ //
153
+ // Finally at the end of all of this the
154
+ // `validate_adapter_module` method is called for a second time
155
+ // on the minimized adapter. This is done because deleting
156
+ // imports may have deleted some imports which means that the
157
+ // final component may not need to import as many interfaces.
158
+ let info = validate_adapter_module (
159
+ & wasm,
134
160
resolve,
135
161
world,
136
- required_exports,
137
162
& required_by_import,
138
- ) ;
163
+ required_exports,
164
+ library_info. as_ref ( ) ,
165
+ adapters,
166
+ )
167
+ . with_context ( || {
168
+ format ! ( "failed to validate the imports of the adapter module `{name}`" )
169
+ } ) ?;
170
+ let mut required = IndexSet :: new ( ) ;
171
+ for ( name, _ty) in required_by_import. iter ( ) {
172
+ required. insert ( name. to_string ( ) ) ;
173
+ }
174
+ for ( name, _export) in info. exports . iter ( ) {
175
+ required. insert ( name. to_string ( ) ) ;
176
+ }
139
177
140
178
Cow :: Owned (
141
179
crate :: gc:: run (
@@ -174,64 +212,6 @@ impl<'a> ComponentWorld<'a> {
174
212
Ok ( ( ) )
175
213
}
176
214
177
- /// Returns the set of functions required to be exported from an adapter,
178
- /// either because they're exported from the adapter's world or because
179
- /// they're required as an import to the main module.
180
- fn required_adapter_exports < ' r > (
181
- & self ,
182
- resolve : & ' r Resolve ,
183
- world : WorldId ,
184
- required_exports : & IndexSet < WorldKey > ,
185
- required_by_import : & IndexMap < String , FuncType > ,
186
- ) -> IndexMap < String , ( FuncType , Option < & ' r Function > ) > {
187
- use wasmparser:: ValType ;
188
-
189
- let mut required = IndexMap :: new ( ) ;
190
- for ( name, ty) in required_by_import {
191
- required. insert ( name. to_string ( ) , ( ty. clone ( ) , None ) ) ;
192
- }
193
- let mut add_func = |func : & ' r Function , name : Option < & str > | {
194
- let name = func. core_export_name ( name) ;
195
- let ty = resolve. wasm_signature ( AbiVariant :: GuestExport , func) ;
196
- let prev = required. insert (
197
- name. into_owned ( ) ,
198
- (
199
- wasmparser:: FuncType :: new (
200
- ty. params . iter ( ) . map ( to_valty) ,
201
- ty. results . iter ( ) . map ( to_valty) ,
202
- ) ,
203
- Some ( func) ,
204
- ) ,
205
- ) ;
206
- assert ! ( prev. is_none( ) ) ;
207
- } ;
208
- for name in required_exports {
209
- match & resolve. worlds [ world] . exports [ name] {
210
- WorldItem :: Function ( func) => add_func ( func, None ) ,
211
- WorldItem :: Interface { id, .. } => {
212
- let name = resolve. name_world_key ( name) ;
213
- for ( _, func) in resolve. interfaces [ * id] . functions . iter ( ) {
214
- add_func ( func, Some ( & name) ) ;
215
- }
216
- }
217
- WorldItem :: Type ( _) => { }
218
- }
219
- }
220
- return required;
221
-
222
- fn to_valty ( ty : & WasmType ) -> ValType {
223
- match ty {
224
- WasmType :: I32 => ValType :: I32 ,
225
- WasmType :: I64 => ValType :: I64 ,
226
- WasmType :: F32 => ValType :: F32 ,
227
- WasmType :: F64 => ValType :: F64 ,
228
- WasmType :: Pointer => ValType :: I32 ,
229
- WasmType :: PointerOrI64 => ValType :: I64 ,
230
- WasmType :: Length => ValType :: I32 ,
231
- }
232
- }
233
- }
234
-
235
215
/// Fills out the `import_map` field of `self` by determining the live
236
216
/// functions from all imports. This additionally classifies imported
237
217
/// functions into direct or indirect lowerings for managing shims.
0 commit comments