@@ -6,9 +6,8 @@ use anyhow::{Context, Result};
66use indexmap:: { IndexMap , IndexSet } ;
77use std:: borrow:: Cow ;
88use std:: collections:: { HashMap , HashSet } ;
9- use wasmparser:: FuncType ;
109use wit_parser:: {
11- abi:: { AbiVariant , WasmSignature , WasmType } ,
10+ abi:: { AbiVariant , WasmSignature } ,
1211 Function , InterfaceId , LiveTypes , Resolve , TypeDefKind , TypeId , TypeOwner , WorldId , WorldItem ,
1312 WorldKey ,
1413} ;
@@ -130,12 +129,51 @@ impl<'a> ComponentWorld<'a> {
130129 let wasm = if library_info. is_some ( ) {
131130 Cow :: Borrowed ( wasm as & [ u8 ] )
132131 } 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,
134160 resolve,
135161 world,
136- required_exports,
137162 & 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+ }
139177
140178 Cow :: Owned (
141179 crate :: gc:: run (
@@ -174,64 +212,6 @@ impl<'a> ComponentWorld<'a> {
174212 Ok ( ( ) )
175213 }
176214
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-
235215 /// Fills out the `import_map` field of `self` by determining the live
236216 /// functions from all imports. This additionally classifies imported
237217 /// functions into direct or indirect lowerings for managing shims.
0 commit comments