wasmer_wit_parser/
abi.rs

1use crate::sizealign::align_to;
2use crate::{
3    Enum, Expected, Flags, FlagsRepr, Function, Int, Interface, Record, ResourceId, Tuple, Type,
4    TypeDefKind, TypeId, Union, Variant,
5};
6use std::mem;
7
8/// A raw WebAssembly signature with params and results.
9#[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
10pub struct WasmSignature {
11    /// The WebAssembly parameters of this function.
12    pub params: Vec<WasmType>,
13
14    /// The WebAssembly results of this function.
15    pub results: Vec<WasmType>,
16
17    /// Whether or not this signature is passing all of its parameters
18    /// indirectly through a pointer within `params`.
19    ///
20    /// Note that `params` still reflects the true wasm paramters of this
21    /// function, this is auxiliary information for code generators if
22    /// necessary.
23    pub indirect_params: bool,
24
25    /// Whether or not this signature is using a return pointer to store the
26    /// result of the function, which is reflected either in `params` or
27    /// `results` depending on the context this function is used (e.g. an import
28    /// or an export).
29    pub retptr: bool,
30}
31
32/// Enumerates wasm types used by interface types when lowering/lifting.
33#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
34pub enum WasmType {
35    I32,
36    I64,
37    F32,
38    F64,
39    // NOTE: we don't lower interface types to any other Wasm type,
40    // e.g. externref, so we don't need to define them here.
41}
42
43fn join(a: WasmType, b: WasmType) -> WasmType {
44    use WasmType::*;
45
46    match (a, b) {
47        (I32, I32) | (I64, I64) | (F32, F32) | (F64, F64) => a,
48
49        (I32, F32) | (F32, I32) => I32,
50
51        (_, I64 | F64) | (I64 | F64, _) => I64,
52    }
53}
54
55impl From<Int> for WasmType {
56    fn from(i: Int) -> WasmType {
57        match i {
58            Int::U8 | Int::U16 | Int::U32 => WasmType::I32,
59            Int::U64 => WasmType::I64,
60        }
61    }
62}
63
64// Helper macro for defining instructions without having to have tons of
65// exhaustive `match` statements to update
66macro_rules! def_instruction {
67    (
68        $( #[$enum_attr:meta] )*
69        pub enum $name:ident<'a> {
70            $(
71                $( #[$attr:meta] )*
72                $variant:ident $( {
73                    $($field:ident : $field_ty:ty $(,)* )*
74                } )?
75                    :
76                [$num_popped:expr] => [$num_pushed:expr],
77            )*
78        }
79    ) => {
80        $( #[$enum_attr] )*
81        pub enum $name<'a> {
82            $(
83                $( #[$attr] )*
84                $variant $( {
85                    $(
86                        $field : $field_ty,
87                    )*
88                } )? ,
89            )*
90        }
91
92        impl $name<'_> {
93            /// How many operands does this instruction pop from the stack?
94            #[allow(unused_variables)]
95            pub fn operands_len(&self) -> usize {
96                match self {
97                    $(
98                        Self::$variant $( {
99                            $(
100                                $field,
101                            )*
102                        } )? => $num_popped,
103                    )*
104                }
105            }
106
107            /// How many results does this instruction push onto the stack?
108            #[allow(unused_variables)]
109            pub fn results_len(&self) -> usize {
110                match self {
111                    $(
112                        Self::$variant $( {
113                            $(
114                                $field,
115                            )*
116                        } )? => $num_pushed,
117                    )*
118                }
119            }
120        }
121    };
122}
123
124def_instruction! {
125    #[derive(Debug)]
126    pub enum Instruction<'a> {
127        /// Acquires the specified parameter and places it on the stack.
128        /// Depending on the context this may refer to wasm parameters or
129        /// interface types parameters.
130        GetArg { nth: usize } : [0] => [1],
131
132        // Integer const/manipulation instructions
133
134        /// Pushes the constant `val` onto the stack.
135        I32Const { val: i32 } : [0] => [1],
136        /// Casts the top N items on the stack using the `Bitcast` enum
137        /// provided. Consumes the same number of operands that this produces.
138        Bitcasts { casts: &'a [Bitcast] } : [casts.len()] => [casts.len()],
139        /// Pushes a number of constant zeros for each wasm type on the stack.
140        ConstZero { tys: &'a [WasmType] } : [0] => [tys.len()],
141
142        // Memory load/store instructions
143
144        /// Pops an `i32` from the stack and loads a little-endian `i32` from
145        /// it, using the specified constant offset.
146        I32Load { offset: i32 } : [1] => [1],
147        /// Pops an `i32` from the stack and loads a little-endian `i8` from
148        /// it, using the specified constant offset. The value loaded is the
149        /// zero-extended to 32-bits
150        I32Load8U { offset: i32 } : [1] => [1],
151        /// Pops an `i32` from the stack and loads a little-endian `i8` from
152        /// it, using the specified constant offset. The value loaded is the
153        /// sign-extended to 32-bits
154        I32Load8S { offset: i32 } : [1] => [1],
155        /// Pops an `i32` from the stack and loads a little-endian `i16` from
156        /// it, using the specified constant offset. The value loaded is the
157        /// zero-extended to 32-bits
158        I32Load16U { offset: i32 } : [1] => [1],
159        /// Pops an `i32` from the stack and loads a little-endian `i16` from
160        /// it, using the specified constant offset. The value loaded is the
161        /// sign-extended to 32-bits
162        I32Load16S { offset: i32 } : [1] => [1],
163        /// Pops an `i32` from the stack and loads a little-endian `i64` from
164        /// it, using the specified constant offset.
165        I64Load { offset: i32 } : [1] => [1],
166        /// Pops an `i32` from the stack and loads a little-endian `f32` from
167        /// it, using the specified constant offset.
168        F32Load { offset: i32 } : [1] => [1],
169        /// Pops an `i32` from the stack and loads a little-endian `f64` from
170        /// it, using the specified constant offset.
171        F64Load { offset: i32 } : [1] => [1],
172
173        /// Pops an `i32` address from the stack and then an `i32` value.
174        /// Stores the value in little-endian at the pointer specified plus the
175        /// constant `offset`.
176        I32Store { offset: i32 } : [2] => [0],
177        /// Pops an `i32` address from the stack and then an `i32` value.
178        /// Stores the low 8 bits of the value in little-endian at the pointer
179        /// specified plus the constant `offset`.
180        I32Store8 { offset: i32 } : [2] => [0],
181        /// Pops an `i32` address from the stack and then an `i32` value.
182        /// Stores the low 16 bits of the value in little-endian at the pointer
183        /// specified plus the constant `offset`.
184        I32Store16 { offset: i32 } : [2] => [0],
185        /// Pops an `i32` address from the stack and then an `i64` value.
186        /// Stores the value in little-endian at the pointer specified plus the
187        /// constant `offset`.
188        I64Store { offset: i32 } : [2] => [0],
189        /// Pops an `i32` address from the stack and then an `f32` value.
190        /// Stores the value in little-endian at the pointer specified plus the
191        /// constant `offset`.
192        F32Store { offset: i32 } : [2] => [0],
193        /// Pops an `i32` address from the stack and then an `f64` value.
194        /// Stores the value in little-endian at the pointer specified plus the
195        /// constant `offset`.
196        F64Store { offset: i32 } : [2] => [0],
197
198        // Scalar lifting/lowering
199
200        /// Converts an interface type `char` value to a 32-bit integer
201        /// representing the unicode scalar value.
202        I32FromChar : [1] => [1],
203        /// Converts an interface type `u64` value to a wasm `i64`.
204        I64FromU64 : [1] => [1],
205        /// Converts an interface type `s64` value to a wasm `i64`.
206        I64FromS64 : [1] => [1],
207        /// Converts an interface type `u32` value to a wasm `i32`.
208        I32FromU32 : [1] => [1],
209        /// Converts an interface type `s32` value to a wasm `i32`.
210        I32FromS32 : [1] => [1],
211        /// Converts an interface type `u16` value to a wasm `i32`.
212        I32FromU16 : [1] => [1],
213        /// Converts an interface type `s16` value to a wasm `i32`.
214        I32FromS16 : [1] => [1],
215        /// Converts an interface type `u8` value to a wasm `i32`.
216        I32FromU8 : [1] => [1],
217        /// Converts an interface type `s8` value to a wasm `i32`.
218        I32FromS8 : [1] => [1],
219        /// Conversion an interface type `f32` value to a wasm `f32`.
220        ///
221        /// This may be a noop for some implementations, but it's here in case the
222        /// native language representation of `f32` is different than the wasm
223        /// representation of `f32`.
224        F32FromFloat32 : [1] => [1],
225        /// Conversion an interface type `f64` value to a wasm `f64`.
226        ///
227        /// This may be a noop for some implementations, but it's here in case the
228        /// native language representation of `f64` is different than the wasm
229        /// representation of `f64`.
230        F64FromFloat64 : [1] => [1],
231
232        /// Converts a native wasm `i32` to an interface type `s8`.
233        ///
234        /// This will truncate the upper bits of the `i32`.
235        S8FromI32 : [1] => [1],
236        /// Converts a native wasm `i32` to an interface type `u8`.
237        ///
238        /// This will truncate the upper bits of the `i32`.
239        U8FromI32 : [1] => [1],
240        /// Converts a native wasm `i32` to an interface type `s16`.
241        ///
242        /// This will truncate the upper bits of the `i32`.
243        S16FromI32 : [1] => [1],
244        /// Converts a native wasm `i32` to an interface type `u16`.
245        ///
246        /// This will truncate the upper bits of the `i32`.
247        U16FromI32 : [1] => [1],
248        /// Converts a native wasm `i32` to an interface type `s32`.
249        S32FromI32 : [1] => [1],
250        /// Converts a native wasm `i32` to an interface type `u32`.
251        U32FromI32 : [1] => [1],
252        /// Converts a native wasm `i64` to an interface type `s64`.
253        S64FromI64 : [1] => [1],
254        /// Converts a native wasm `i64` to an interface type `u64`.
255        U64FromI64 : [1] => [1],
256        /// Converts a native wasm `i32` to an interface type `char`.
257        ///
258        /// It's safe to assume that the `i32` is indeed a valid unicode code point.
259        CharFromI32 : [1] => [1],
260        /// Converts a native wasm `f32` to an interface type `f32`.
261        Float32FromF32 : [1] => [1],
262        /// Converts a native wasm `f64` to an interface type `f64`.
263        Float64FromF64 : [1] => [1],
264
265        /// Creates a `bool` from an `i32` input, trapping if the `i32` isn't
266        /// zero or one.
267        BoolFromI32 : [1] => [1],
268        /// Creates an `i32` from a `bool` input, must return 0 or 1.
269        I32FromBool : [1] => [1],
270
271        /// Creates a "unit" value from nothing.
272        UnitLift : [0] => [1],
273        /// Consumes a "unit" value and returns nothing.
274        UnitLower : [1] => [0],
275
276        // Handles
277
278        /// Converts a "borrowed" handle into a wasm `i32` value.
279        ///
280        /// > **Note**: this documentation is outdated and does not reflect the
281        /// > current implementation of the canonical ABI. This needs to be
282        /// > updated.
283        ///
284        /// A "borrowed" handle in this case means one where ownership is not
285        /// being relinquished. This is only used for lowering interface types
286        /// parameters.
287        ///
288        /// Situations that this is used are:
289        ///
290        /// * A wasm exported function receives, as a parameter, handles defined
291        ///   by the wasm module itself. This is effectively proof of ownership
292        ///   by an external caller (be it host or wasm module) and the
293        ///   ownership of the handle still lies with the caller. The wasm
294        ///   module is only receiving a reference to the resource.
295        ///
296        /// * A wasm module is calling an import with a handle defined by the
297        ///   import's module. Sort of the converse of the previous case this
298        ///   means that the wasm module is handing out a reference to a
299        ///   resource that it owns. The type in the wasm module, for example,
300        ///   needs to reflect this.
301        ///
302        /// This instruction is not used for return values in either
303        /// export/import positions.
304        I32FromBorrowedHandle { ty: ResourceId } : [1] => [1],
305
306        /// Converts an "owned" handle into a wasm `i32` value.
307        ///
308        /// > **Note**: this documentation is outdated and does not reflect the
309        /// > current implementation of the canonical ABI. This needs to be
310        /// > updated.
311        ///
312        /// This conversion is used for handle values which are crossing a
313        /// module boundary for perhaps the first time. Some example cases of
314        /// when this conversion is used are:
315        ///
316        /// * When a host defines a function to be imported, returned handles
317        ///   use this instruction. Handles being returned to wasm a granting a
318        ///   capability, which means that this new capability is typically
319        ///   wrapped up in a new integer descriptor.
320        ///
321        /// * When a wasm module calls an imported function with a type defined
322        ///   by itself, then it's granting a capability to the callee. This
323        ///   means that the wasm module's type is being granted for the first
324        ///   time, possibly, so it needs to be an owned value that's consumed.
325        ///   Note that this doesn't actually happen with `*.witx` today due to
326        ///   the lack of handle type imports.
327        ///
328        /// * When a wasm module export returns a handle defined within the
329        ///   module, then it's similar to calling an imported function with
330        ///   that handle. The capability is being granted to the caller of the
331        ///   export, so the owned value is wrapped up in an `i32`.
332        ///
333        /// * When a host is calling a wasm module with a capability defined by
334        ///   the host, its' similar to the host import returning a capability.
335        ///   This would be granting the wasm module with the capability so an
336        ///   owned version with a fresh handle is passed to the wasm module.
337        ///   Note that this doesn't happen today with `*.witx` due to the lack
338        ///   of handle type imports.
339        ///
340        /// Basically this instruction is used for handle->wasm conversions
341        /// depending on the calling context and where the handle type in
342        /// question was defined.
343        I32FromOwnedHandle { ty: ResourceId } : [1] => [1],
344
345        /// Converts a native wasm `i32` into an owned handle value.
346        ///
347        /// > **Note**: this documentation is outdated and does not reflect the
348        /// > current implementation of the canonical ABI. This needs to be
349        /// > updated.
350        ///
351        /// This is the converse of `I32FromOwnedHandle` and is used in similar
352        /// situations:
353        ///
354        /// * A host definition of an import receives a handle defined in the
355        ///   module itself.
356        /// * A wasm module calling an import receives a handle defined by the
357        ///   import.
358        /// * A wasm module's export receives a handle defined by an external
359        ///   module.
360        /// * A host calling a wasm export receives a handle defined in the
361        ///   module.
362        ///
363        /// Note that like `I32FromOwnedHandle` the first and third bullets
364        /// above don't happen today because witx can't express type imports
365        /// just yet.
366        HandleOwnedFromI32 { ty: ResourceId } : [1] => [1],
367
368        /// Converts a native wasm `i32` into a borrowedhandle value.
369        ///
370        /// > **Note**: this documentation is outdated and does not reflect the
371        /// > current implementation of the canonical ABI. This needs to be
372        /// > updated.
373        ///
374        /// This is the converse of `I32FromBorrowedHandle` and is used in similar
375        /// situations:
376        ///
377        /// * An exported wasm function receives, as a parameter, a handle that
378        ///   is defined by the wasm module.
379        /// * An host-defined imported function is receiving a handle, as a
380        ///   parameter, that is defined by the host itself.
381        HandleBorrowedFromI32 { ty: ResourceId } : [1] => [1],
382
383        // lists
384
385        /// Lowers a list where the element's layout in the native language is
386        /// expected to match the canonical ABI definition of interface types.
387        ///
388        /// Pops a list value from the stack and pushes the pointer/length onto
389        /// the stack. If `realloc` is set to `Some` then this is expected to
390        /// *consume* the list which means that the data needs to be copied. An
391        /// allocation/copy is expected when:
392        ///
393        /// * A host is calling a wasm export with a list (it needs to copy the
394        ///   list in to the callee's module, allocating space with `realloc`)
395        /// * A wasm export is returning a list (it's expected to use `realloc`
396        ///   to give ownership of the list to the caller.
397        /// * A host is returning a list in a import definition, meaning that
398        ///   space needs to be allocated in the caller with `realloc`).
399        ///
400        /// A copy does not happen (e.g. `realloc` is `None`) when:
401        ///
402        /// * A wasm module calls an import with the list. In this situation
403        ///   it's expected the caller will know how to access this module's
404        ///   memory (e.g. the host has raw access or wasm-to-wasm communication
405        ///   would copy the list).
406        ///
407        /// If `realloc` is `Some` then the adapter is not responsible for
408        /// cleaning up this list because the other end is receiving the
409        /// allocation. If `realloc` is `None` then the adapter is responsible
410        /// for cleaning up any temporary allocation it created, if any.
411        ListCanonLower {
412            element: &'a Type,
413            realloc: Option<&'a str>,
414        } : [1] => [2],
415
416        /// Same as `ListCanonLower`, but used for strings
417        StringLower {
418            realloc: Option<&'a str>,
419        } : [1] => [2],
420
421        /// Lowers a list where the element's layout in the native language is
422        /// not expected to match the canonical ABI definition of interface
423        /// types.
424        ///
425        /// Pops a list value from the stack and pushes the pointer/length onto
426        /// the stack. This operation also pops a block from the block stack
427        /// which is used as the iteration body of writing each element of the
428        /// list consumed.
429        ///
430        /// The `realloc` field here behaves the same way as `ListCanonLower`.
431        /// It's only set to `None` when a wasm module calls a declared import.
432        /// Otherwise lowering in other contexts requires allocating memory for
433        /// the receiver to own.
434        ListLower {
435            element: &'a Type,
436            realloc: Option<&'a str>,
437        } : [1] => [2],
438
439        /// Lifts a list which has a canonical representation into an interface
440        /// types value.
441        ///
442        /// The term "canonical" representation here means that the
443        /// representation of the interface types value in the native language
444        /// exactly matches the canonical ABI definition of the type.
445        ///
446        /// This will consume two `i32` values from the stack, a pointer and a
447        /// length, and then produces an interface value list. If the `free`
448        /// field is set to `Some` then the pointer/length should be considered
449        /// an owned allocation and need to be deallocated by the receiver. If
450        /// it is set to `None` then a view is provided but it does not need to
451        /// be deallocated.
452        ///
453        /// The `free` field is set to `Some` in similar situations as described
454        /// by `ListCanonLower`. If `free` is `Some` then the memory must be
455        /// deallocated after the lifted list is done being consumed. If it is
456        /// `None` then the receiver of the lifted list does not own the memory
457        /// and must leave the memory as-is.
458        ListCanonLift {
459            element: &'a Type,
460            free: Option<&'a str>,
461            ty: TypeId,
462        } : [2] => [1],
463
464        /// Same as `ListCanonLift`, but used for strings
465        StringLift {
466            free: Option<&'a str>,
467        } : [2] => [1],
468
469        /// Lifts a list which into an interface types value.
470        ///
471        /// This will consume two `i32` values from the stack, a pointer and a
472        /// length, and then produces an interface value list. Note that the
473        /// pointer/length popped are **owned** and need to be deallocated with
474        /// the wasm `free` function when the list is no longer needed.
475        ///
476        /// This will also pop a block from the block stack which is how to
477        /// read each individual element from the list.
478        ListLift {
479            element: &'a Type,
480            free: Option<&'a str>,
481            ty: TypeId,
482        } : [2] => [1],
483
484        /// Pushes an operand onto the stack representing the list item from
485        /// each iteration of the list.
486        ///
487        /// This is only used inside of blocks related to lowering lists.
488        IterElem { element: &'a Type } : [0] => [1],
489
490        /// Pushes an operand onto the stack representing the base pointer of
491        /// the next element in a list.
492        ///
493        /// This is used for both lifting and lowering lists.
494        IterBasePointer : [0] => [1],
495
496        // records
497
498        /// Pops a record value off the stack, decomposes the record to all of
499        /// its fields, and then pushes the fields onto the stack.
500        RecordLower {
501            record: &'a Record,
502            name: &'a str,
503            ty: TypeId,
504        } : [1] => [record.fields.len()],
505
506        /// Pops all fields for a record off the stack and then composes them
507        /// into a record.
508        RecordLift {
509            record: &'a Record,
510            name: &'a str,
511            ty: TypeId,
512        } : [record.fields.len()] => [1],
513
514        /// Pops a tuple value off the stack, decomposes the tuple to all of
515        /// its fields, and then pushes the fields onto the stack.
516        TupleLower {
517            tuple: &'a Tuple,
518            ty: TypeId,
519        } : [1] => [tuple.types.len()],
520
521        /// Pops all fields for a tuple off the stack and then composes them
522        /// into a tuple.
523        TupleLift {
524            tuple: &'a Tuple,
525            ty: TypeId,
526        } : [tuple.types.len()] => [1],
527
528        /// Converts a language-specific record-of-bools to a list of `i32`.
529        FlagsLower {
530            flags: &'a Flags,
531            name: &'a str,
532            ty: TypeId,
533        } : [1] => [flags.repr().count()],
534        /// Converts a list of native wasm `i32` to a language-specific
535        /// record-of-bools.
536        FlagsLift {
537            flags: &'a Flags,
538            name: &'a str,
539            ty: TypeId,
540        } : [flags.repr().count()] => [1],
541
542        // variants
543
544        /// This is a special instruction used for `VariantLower`
545        /// instruction to determine the name of the payload, if present, to use
546        /// within each block.
547        ///
548        /// Each sub-block will have this be the first instruction, and if it
549        /// lowers a payload it will expect something bound to this name.
550        VariantPayloadName : [0] => [1],
551
552        /// Pops a variant off the stack as well as `ty.cases.len()` blocks
553        /// from the code generator. Uses each of those blocks and the value
554        /// from the stack to produce `nresults` of items.
555        VariantLower {
556            variant: &'a Variant,
557            name: &'a str,
558            ty: TypeId,
559            results: &'a [WasmType],
560        } : [1] => [results.len()],
561
562        /// Pops an `i32` off the stack as well as `ty.cases.len()` blocks
563        /// from the code generator. Uses each of those blocks and the value
564        /// from the stack to produce a final variant.
565        VariantLift {
566            variant: &'a Variant,
567            name: &'a str,
568            ty: TypeId,
569        } : [1] => [1],
570
571        /// Same as `VariantLower`, except used for unions.
572        UnionLower {
573            union: &'a Union,
574            name: &'a str,
575            ty: TypeId,
576            results: &'a [WasmType],
577        } : [1] => [results.len()],
578
579        /// Same as `VariantLift`, except used for unions.
580        UnionLift {
581            union: &'a Union,
582            name: &'a str,
583            ty: TypeId,
584        } : [1] => [1],
585
586        /// Pops an enum off the stack and pushes the `i32` representation.
587        EnumLower {
588            enum_: &'a Enum,
589            name: &'a str,
590            ty: TypeId,
591        } : [1] => [1],
592
593        /// Pops an `i32` off the stack and lifts it into the `enum` specified.
594        EnumLift {
595            enum_: &'a Enum,
596            name: &'a str,
597            ty: TypeId,
598        } : [1] => [1],
599
600        /// Specialization of `VariantLower` for specifically `option<T>` types,
601        /// otherwise behaves the same as `VariantLower` (e.g. two blocks for
602        /// the two cases.
603        OptionLower {
604            payload: &'a Type,
605            ty: TypeId,
606            results: &'a [WasmType],
607        } : [1] => [results.len()],
608
609        /// Specialization of `VariantLift` for specifically the `option<T>`
610        /// type. Otherwise behaves the same as the `VariantLift` instruction
611        /// with two blocks for the lift.
612        OptionLift {
613            payload: &'a Type,
614            ty: TypeId,
615        } : [1] => [1],
616
617        /// Specialization of `VariantLower` for specifically `expected<T, E>`
618        /// types, otherwise behaves the same as `VariantLower` (e.g. two blocks
619        /// for the two cases.
620        ExpectedLower {
621            expected: &'a Expected,
622            ty: TypeId,
623            results: &'a [WasmType],
624        } : [1] => [results.len()],
625
626        /// Specialization of `VariantLift` for specifically the `expected<T,
627        /// E>` type. Otherwise behaves the same as the `VariantLift`
628        /// instruction with two blocks for the lift.
629        ExpectedLift {
630            expected: &'a Expected,
631            ty: TypeId,
632        } : [1] => [1],
633
634        // calling/control flow
635
636        /// Represents a call to a raw WebAssembly API. The module/name are
637        /// provided inline as well as the types if necessary.
638        ///
639        /// Note that this instruction is not currently used for async
640        /// functions, instead `CallWasmAsyncImport` and `CallWasmAsyncExport`
641        /// are used.
642        CallWasm {
643            iface: &'a Interface,
644            name: &'a str,
645            sig: &'a WasmSignature,
646        } : [sig.params.len()] => [sig.results.len()],
647
648        /// Represents a call to an asynchronous wasm import.
649        ///
650        /// This currently only happens when a compiled-to-wasm module calls as
651        /// async import. This instruction is used to indicate that the
652        /// specified import function should be called. The specified import
653        /// function has `params` as its types, but the final two parameters
654        /// must be synthesized by this instruction which are the
655        /// callback/callback state. The actual imported function does not
656        /// return anything but the callback will be called with the `i32` state
657        /// as the first parameter and `results` as the rest of the parameters.
658        /// The callback function should return nothing.
659        ///
660        /// It's up to the bindings generator to figure out how to make this
661        /// look synchronous despite it being callback-based in the middle.
662        CallWasmAsyncImport {
663            iface: &'a Interface,
664            name: &'a str,
665            params: &'a [WasmType],
666            results: &'a [WasmType],
667        } : [params.len() - 2] => [results.len()],
668
669        /// Represents a call to an asynchronous wasm export.
670        ///
671        /// This currently only happens when a host module calls an async
672        /// function on a wasm module. The specified function will take `params`
673        /// as its argument plus one more argument of an `i32` state that the
674        /// host needs to synthesize. The function being called doesn't actually
675        /// return anything. Instead wasm will call an `async_export_done`
676        /// intrinsic in the `canonical_abi` module. This intrinsic receives a
677        /// context value and a pointer into linear memory. The context value
678        /// lines up with the final `i32` parameter of this function call (which
679        /// the bindings generator must synthesize) and the pointer into linear
680        /// memory contains the `results`, stored at 8-byte offsets in the same
681        /// manner that multiple results are transferred.
682        ///
683        /// It's up to the bindings generator to figure out how to make this
684        /// look synchronous despite it being callback-based in the middle.
685        CallWasmAsyncExport {
686            module: &'a str,
687            name: &'a str,
688            params: &'a [WasmType],
689            results: &'a [WasmType],
690        } : [params.len() - 1] => [results.len()],
691
692        /// Same as `CallWasm`, except the dual where an interface is being
693        /// called rather than a raw wasm function.
694        ///
695        /// Note that this will be used for async functions.
696        CallInterface {
697            module: &'a str,
698            func: &'a Function,
699        } : [func.params.len()] => [1],
700
701        /// Returns `amt` values on the stack. This is always the last
702        /// instruction.
703        ///
704        /// Note that this instruction is used for asynchronous functions where
705        /// the results are *lifted*, not when they're *lowered*, though. For
706        /// those modes the `ReturnAsyncExport` and `ReturnAsyncImport`
707        /// functions are used.
708        Return { amt: usize, func: &'a Function } : [*amt] => [0],
709
710        /// "Returns" from an asynchronous export.
711        ///
712        /// This is only used for compiled-to-wasm modules at this time, and
713        /// only for the exports of async functions in those modules. This
714        /// instruction receives two parameters, the first of which is the
715        /// original context from the start of the function which was provided
716        /// when the export was first called (its last parameter). The second
717        /// argument is a pointer into linear memory with the results of the
718        /// asynchronous call already encoded. This instruction should then call
719        /// the `async_export_done` intrinsic in the `canonical_abi` module.
720        ReturnAsyncExport { func: &'a Function } : [2] => [0],
721
722        /// "Returns" from an asynchronous import.
723        ///
724        /// This is only used for host modules at this time, and
725        /// only for the import of async functions in those modules. This
726        /// instruction receives the operands used to call the completion
727        /// function in the wasm module. The first parameter to this instruction
728        /// is the index into the function table of the function to call, and
729        /// the remaining parameters are the parameters to invoke the function
730        /// with.
731        ReturnAsyncImport {
732            func: &'a Function,
733            params: usize,
734        } : [*params + 2] => [0],
735
736        /// Calls the `realloc` function specified in a malloc-like fashion
737        /// allocating `size` bytes with alignment `align`.
738        ///
739        /// Pushes the returned pointer onto the stack.
740        Malloc {
741            realloc: &'static str,
742            size: usize,
743            align: usize,
744        } : [0] => [1],
745
746        /// Calls the `free` function specified to deallocate the pointer on the
747        /// stack which has `size` bytes with alignment `align`.
748        Free {
749            free: &'static str,
750            size: usize,
751            align: usize,
752        } : [1] => [0],
753    }
754}
755
756#[derive(Debug, PartialEq)]
757pub enum Bitcast {
758    // Upcasts
759    F32ToI32,
760    F64ToI64,
761    I32ToI64,
762    F32ToI64,
763
764    // Downcasts
765    I32ToF32,
766    I64ToF64,
767    I64ToI32,
768    I64ToF32,
769
770    None,
771}
772
773/// Whether the glue code surrounding a call is lifting arguments and lowering
774/// results or vice versa.
775#[derive(Clone, Copy, PartialEq, Eq)]
776pub enum LiftLower {
777    /// When the glue code lifts arguments and lowers results.
778    ///
779    /// ```text
780    /// Wasm --lift-args--> SourceLanguage; call; SourceLanguage --lower-results--> Wasm
781    /// ```
782    LiftArgsLowerResults,
783    /// When the glue code lowers arguments and lifts results.
784    ///
785    /// ```text
786    /// SourceLanguage --lower-args--> Wasm; call; Wasm --lift-results--> SourceLanguage
787    /// ```
788    LowerArgsLiftResults,
789}
790
791/// We use a different ABI for wasm importing functions exported by the host
792/// than for wasm exporting functions imported by the host.
793///
794/// Note that this reflects the flavor of ABI we generate, and not necessarily
795/// the way the resulting bindings will be used by end users. See the comments
796/// on the `Direction` enum in gen-core for details.
797///
798/// The bindings ABI has a concept of a "guest" and a "host". There are two
799/// variants of the ABI, one specialized for the "guest" importing and calling
800/// a function defined and exported in the "host", and the other specialized for
801/// the "host" importing and calling a function defined and exported in the "guest".
802#[derive(Clone, Copy, PartialEq, Eq, Debug)]
803pub enum AbiVariant {
804    /// The guest is importing and calling the function.
805    GuestImport,
806    /// The guest is defining and exporting the function.
807    GuestExport,
808}
809
810/// Trait for language implementors to use to generate glue code between native
811/// WebAssembly signatures and interface types signatures.
812///
813/// This is used as an implementation detail in interpreting the ABI between
814/// interface types and wasm types. Eventually this will be driven by interface
815/// types adapters themselves, but for now the ABI of a function dictates what
816/// instructions are fed in.
817///
818/// Types implementing `Bindgen` are incrementally fed `Instruction` values to
819/// generate code for. Instructions operate like a stack machine where each
820/// instruction has a list of inputs and a list of outputs (provided by the
821/// `emit` function).
822pub trait Bindgen {
823    /// The intermediate type for fragments of code for this type.
824    ///
825    /// For most languages `String` is a suitable intermediate type.
826    type Operand: Clone;
827
828    /// Emit code to implement the given instruction.
829    ///
830    /// Each operand is given in `operands` and can be popped off if ownership
831    /// is required. It's guaranteed that `operands` has the appropriate length
832    /// for the `inst` given, as specified with [`Instruction`].
833    ///
834    /// Each result variable should be pushed onto `results`. This function must
835    /// push the appropriate number of results or binding generation will panic.
836    fn emit(
837        &mut self,
838        iface: &Interface,
839        inst: &Instruction<'_>,
840        operands: &mut Vec<Self::Operand>,
841        results: &mut Vec<Self::Operand>,
842    );
843
844    /// Gets a operand reference to the return pointer area.
845    ///
846    /// The provided size and alignment is for the function's return type.
847    fn return_pointer(&mut self, iface: &Interface, size: usize, align: usize) -> Self::Operand;
848
849    /// Enters a new block of code to generate code for.
850    ///
851    /// This is currently exclusively used for constructing variants. When a
852    /// variant is constructed a block here will be pushed for each case of a
853    /// variant, generating the code necessary to translate a variant case.
854    ///
855    /// Blocks are completed with `finish_block` below. It's expected that `emit`
856    /// will always push code (if necessary) into the "current block", which is
857    /// updated by calling this method and `finish_block` below.
858    fn push_block(&mut self);
859
860    /// Indicates to the code generator that a block is completed, and the
861    /// `operand` specified was the resulting value of the block.
862    ///
863    /// This method will be used to compute the value of each arm of lifting a
864    /// variant. The `operand` will be `None` if the variant case didn't
865    /// actually have any type associated with it. Otherwise it will be `Some`
866    /// as the last value remaining on the stack representing the value
867    /// associated with a variant's `case`.
868    ///
869    /// It's expected that this will resume code generation in the previous
870    /// block before `push_block` was called. This must also save the results
871    /// of the current block internally for instructions like `ResultLift` to
872    /// use later.
873    fn finish_block(&mut self, operand: &mut Vec<Self::Operand>);
874
875    /// Returns size information that was previously calculated for all types.
876    fn sizes(&self) -> &crate::sizealign::SizeAlign;
877
878    /// Returns whether or not the specified element type is represented in a
879    /// "canonical" form for lists. This dictates whether the `ListCanonLower`
880    /// and `ListCanonLift` instructions are used or not.
881    fn is_list_canonical(&self, iface: &Interface, element: &Type) -> bool;
882}
883
884impl Interface {
885    /// Get the WebAssembly type signature for this interface function
886    ///
887    /// The first entry returned is the list of parameters and the second entry
888    /// is the list of results for the wasm function signature.
889    pub fn wasm_signature(&self, variant: AbiVariant, func: &Function) -> WasmSignature {
890        const MAX_FLAT_PARAMS: usize = 16;
891        const MAX_FLAT_RESULTS: usize = 1;
892
893        let mut params = Vec::new();
894        let mut indirect_params = false;
895        for (_, param) in func.params.iter() {
896            self.push_wasm(variant, param, &mut params);
897        }
898
899        if params.len() > MAX_FLAT_PARAMS {
900            params.truncate(0);
901            params.push(WasmType::I32);
902            indirect_params = true;
903        }
904
905        let mut results = Vec::new();
906        self.push_wasm(variant, &func.result, &mut results);
907
908        let mut retptr = false;
909        if func.is_async {
910            // Asynchronous functions never actually return anything since
911            // they're all callback-based, meaning that we always put all the
912            // results into a return pointer.
913            //
914            // Asynchronous exports take one extra parameter which is the
915            // context used to pass to the `async_export_done` intrinsic, and
916            // asynchronous imports take two extra parameters where the first is
917            // a pointer into the function table and the second is a context
918            // argument to pass to this function.
919            match variant {
920                AbiVariant::GuestExport => {
921                    retptr = true;
922                    results.truncate(0);
923                    params.push(WasmType::I32);
924                }
925                AbiVariant::GuestImport => {
926                    retptr = true;
927                    results.truncate(0);
928                    params.push(WasmType::I32);
929                    params.push(WasmType::I32);
930                }
931            }
932        } else {
933            // Rust/C don't support multi-value well right now, so if a function
934            // would have multiple results then instead truncate it. Imports take a
935            // return pointer to write into and exports return a pointer they wrote
936            // into.
937            if results.len() > MAX_FLAT_RESULTS {
938                retptr = true;
939                results.truncate(0);
940                match variant {
941                    AbiVariant::GuestImport => {
942                        params.push(WasmType::I32);
943                    }
944                    AbiVariant::GuestExport => {
945                        results.push(WasmType::I32);
946                    }
947                }
948            }
949        }
950
951        WasmSignature {
952            params,
953            indirect_params,
954            results,
955            retptr,
956        }
957    }
958
959    fn push_wasm(&self, variant: AbiVariant, ty: &Type, result: &mut Vec<WasmType>) {
960        match ty {
961            Type::Unit => {}
962
963            Type::Bool
964            | Type::S8
965            | Type::U8
966            | Type::S16
967            | Type::U16
968            | Type::S32
969            | Type::U32
970            | Type::Char
971            | Type::Handle(_) => result.push(WasmType::I32),
972
973            Type::U64 | Type::S64 => result.push(WasmType::I64),
974            Type::Float32 => result.push(WasmType::F32),
975            Type::Float64 => result.push(WasmType::F64),
976            Type::String => {
977                result.push(WasmType::I32);
978                result.push(WasmType::I32);
979            }
980
981            Type::Id(id) => match &self.types[*id].kind {
982                TypeDefKind::Type(t) => self.push_wasm(variant, t, result),
983
984                TypeDefKind::Record(r) => {
985                    for field in r.fields.iter() {
986                        self.push_wasm(variant, &field.ty, result);
987                    }
988                }
989
990                TypeDefKind::Tuple(t) => {
991                    for ty in t.types.iter() {
992                        self.push_wasm(variant, ty, result);
993                    }
994                }
995
996                TypeDefKind::Flags(r) => {
997                    for _ in 0..r.repr().count() {
998                        result.push(WasmType::I32);
999                    }
1000                }
1001
1002                TypeDefKind::List(_) => {
1003                    result.push(WasmType::I32);
1004                    result.push(WasmType::I32);
1005                }
1006
1007                TypeDefKind::Variant(v) => {
1008                    result.push(v.tag().into());
1009                    self.push_wasm_variants(variant, v.cases.iter().map(|c| &c.ty), result);
1010                }
1011
1012                TypeDefKind::Enum(e) => result.push(e.tag().into()),
1013
1014                TypeDefKind::Option(t) => {
1015                    result.push(WasmType::I32);
1016                    self.push_wasm_variants(variant, [&Type::Unit, t], result);
1017                }
1018
1019                TypeDefKind::Expected(e) => {
1020                    result.push(WasmType::I32);
1021                    self.push_wasm_variants(variant, [&e.ok, &e.err], result);
1022                }
1023
1024                TypeDefKind::Union(u) => {
1025                    result.push(WasmType::I32);
1026                    self.push_wasm_variants(variant, u.cases.iter().map(|c| &c.ty), result);
1027                }
1028
1029                TypeDefKind::Future(_) => {
1030                    result.push(WasmType::I32);
1031                }
1032
1033                TypeDefKind::Stream(_) => {
1034                    result.push(WasmType::I32);
1035                }
1036            },
1037        }
1038    }
1039
1040    fn push_wasm_variants<'a>(
1041        &self,
1042        variant: AbiVariant,
1043        tys: impl IntoIterator<Item = &'a Type>,
1044        result: &mut Vec<WasmType>,
1045    ) {
1046        let mut temp = Vec::new();
1047        let start = result.len();
1048
1049        // Push each case's type onto a temporary vector, and then
1050        // merge that vector into our final list starting at
1051        // `start`. Note that this requires some degree of
1052        // "unification" so we can handle things like `Result<i32,
1053        // f32>` where that turns into `[i32 i32]` where the second
1054        // `i32` might be the `f32` bitcasted.
1055        for ty in tys {
1056            self.push_wasm(variant, ty, &mut temp);
1057
1058            for (i, ty) in temp.drain(..).enumerate() {
1059                match result.get_mut(start + i) {
1060                    Some(prev) => *prev = join(*prev, ty),
1061                    None => result.push(ty),
1062                }
1063            }
1064        }
1065    }
1066
1067    /// Generates an abstract sequence of instructions which represents this
1068    /// function being adapted as an imported function.
1069    ///
1070    /// The instructions here, when executed, will emulate a language with
1071    /// interface types calling the concrete wasm implementation. The parameters
1072    /// for the returned instruction sequence are the language's own
1073    /// interface-types parameters. One instruction in the instruction stream
1074    /// will be a `Call` which represents calling the actual raw wasm function
1075    /// signature.
1076    ///
1077    /// This function is useful, for example, if you're building a language
1078    /// generator for WASI bindings. This will document how to translate
1079    /// language-specific values into the wasm types to call a WASI function,
1080    /// and it will also automatically convert the results of the WASI function
1081    /// back to a language-specific value.
1082    pub fn call(
1083        &self,
1084        variant: AbiVariant,
1085        lift_lower: LiftLower,
1086        func: &Function,
1087        bindgen: &mut impl Bindgen,
1088    ) {
1089        Generator::new(self, variant, lift_lower, bindgen).call(func);
1090    }
1091}
1092
1093struct Generator<'a, B: Bindgen> {
1094    variant: AbiVariant,
1095    lift_lower: LiftLower,
1096    bindgen: &'a mut B,
1097    iface: &'a Interface,
1098    operands: Vec<B::Operand>,
1099    results: Vec<B::Operand>,
1100    stack: Vec<B::Operand>,
1101    return_pointer: Option<B::Operand>,
1102}
1103
1104impl<'a, B: Bindgen> Generator<'a, B> {
1105    fn new(
1106        iface: &'a Interface,
1107        variant: AbiVariant,
1108        lift_lower: LiftLower,
1109        bindgen: &'a mut B,
1110    ) -> Generator<'a, B> {
1111        Generator {
1112            iface,
1113            variant,
1114            lift_lower,
1115            bindgen,
1116            operands: Vec::new(),
1117            results: Vec::new(),
1118            stack: Vec::new(),
1119            return_pointer: None,
1120        }
1121    }
1122
1123    fn call(&mut self, func: &Function) {
1124        let sig = self.iface.wasm_signature(self.variant, func);
1125
1126        match self.lift_lower {
1127            LiftLower::LowerArgsLiftResults => {
1128                if !sig.indirect_params {
1129                    // If the parameters for this function aren't indirect
1130                    // (there aren't too many) then we simply do a normal lower
1131                    // operation for them all.
1132                    for (nth, (_, ty)) in func.params.iter().enumerate() {
1133                        self.emit(&Instruction::GetArg { nth });
1134                        self.lower(ty);
1135                    }
1136                } else {
1137                    // ... otherwise if parameters are indirect space is
1138                    // allocated from them and each argument is lowered
1139                    // individually into memory.
1140                    let (size, align) = self
1141                        .bindgen
1142                        .sizes()
1143                        .record(func.params.iter().map(|t| &t.1));
1144                    let ptr = match self.variant {
1145                        // When a wasm module calls an import it will provide
1146                        // static space that isn't dynamically allocated.
1147                        AbiVariant::GuestImport => {
1148                            self.bindgen.return_pointer(self.iface, size, align)
1149                        }
1150                        // When calling a wasm module from the outside, though,
1151                        // malloc needs to be called.
1152                        AbiVariant::GuestExport => {
1153                            self.emit(&Instruction::Malloc {
1154                                realloc: "canonical_abi_realloc",
1155                                size,
1156                                align,
1157                            });
1158                            self.stack.pop().unwrap()
1159                        }
1160                    };
1161                    let mut offset = 0usize;
1162                    for (nth, (_, ty)) in func.params.iter().enumerate() {
1163                        self.emit(&Instruction::GetArg { nth });
1164                        offset = align_to(offset, self.bindgen.sizes().align(ty));
1165                        self.write_to_memory(ty, ptr.clone(), offset as i32);
1166                        offset += self.bindgen.sizes().size(ty);
1167                    }
1168
1169                    self.stack.push(ptr);
1170                }
1171
1172                if func.is_async {
1173                    // We emit custom instructions for async calls since they
1174                    // have different parameters synthesized by the bindings
1175                    // generator depending on what kind of call is being made.
1176                    //
1177                    // Note that no return pointer goop happens here because
1178                    // that's all done through parameters of callbacks instead.
1179                    let mut results = Vec::new();
1180                    self.iface
1181                        .push_wasm(self.variant, &func.result, &mut results);
1182                    match self.variant {
1183                        AbiVariant::GuestImport => {
1184                            assert_eq!(self.stack.len(), sig.params.len() - 2);
1185                            self.emit(&Instruction::CallWasmAsyncImport {
1186                                iface: self.iface,
1187                                name: &func.name,
1188                                params: &sig.params,
1189                                results: &results,
1190                            });
1191                        }
1192                        AbiVariant::GuestExport => {
1193                            assert_eq!(self.stack.len(), sig.params.len() - 1);
1194                            self.emit(&Instruction::CallWasmAsyncExport {
1195                                module: &self.iface.name,
1196                                name: &func.name,
1197                                params: &sig.params,
1198                                results: &results,
1199                            });
1200                        }
1201                    }
1202
1203                    self.lift(&func.result);
1204                } else {
1205                    // If necessary we may need to prepare a return pointer for
1206                    // this ABI.
1207                    if self.variant == AbiVariant::GuestImport && sig.retptr {
1208                        let size = self.bindgen.sizes().size(&func.result);
1209                        let align = self.bindgen.sizes().align(&func.result);
1210                        let ptr = self.bindgen.return_pointer(self.iface, size, align);
1211                        self.return_pointer = Some(ptr.clone());
1212                        self.stack.push(ptr);
1213                    }
1214
1215                    // Now that all the wasm args are prepared we can call the
1216                    // actual wasm function.
1217                    assert_eq!(self.stack.len(), sig.params.len());
1218                    self.emit(&Instruction::CallWasm {
1219                        iface: self.iface,
1220                        name: &func.name,
1221                        sig: &sig,
1222                    });
1223
1224                    if !sig.retptr {
1225                        // With no return pointer in use we can simply lift the
1226                        // result of the function from the result of the core
1227                        // wasm function.
1228                        self.lift(&func.result);
1229                    } else {
1230                        let ptr = match self.variant {
1231                            // imports into guests means it's a wasm module
1232                            // calling an imported function. We supplied the
1233                            // return poitner as the last argument (saved in
1234                            // `self.return_pointer`) so we use that to read
1235                            // the result of the function from memory.
1236                            AbiVariant::GuestImport => {
1237                                assert!(sig.results.len() == 0);
1238                                self.return_pointer.take().unwrap()
1239                            }
1240
1241                            // guest exports means that this is a host
1242                            // calling wasm so wasm returned a pointer to where
1243                            // the result is stored
1244                            AbiVariant::GuestExport => self.stack.pop().unwrap(),
1245                        };
1246
1247                        self.read_from_memory(&func.result, ptr, 0);
1248                    }
1249                }
1250
1251                self.emit(&Instruction::Return { func, amt: 1 });
1252            }
1253            LiftLower::LiftArgsLowerResults => {
1254                if !sig.indirect_params {
1255                    // If parameters are not passed indirectly then we lift each
1256                    // argument in succession from the component wasm types that
1257                    // make-up the type.
1258                    let mut offset = 0;
1259                    let mut temp = Vec::new();
1260                    for (_, ty) in func.params.iter() {
1261                        temp.truncate(0);
1262                        self.iface.push_wasm(self.variant, ty, &mut temp);
1263                        for _ in 0..temp.len() {
1264                            self.emit(&Instruction::GetArg { nth: offset });
1265                            offset += 1;
1266                        }
1267                        self.lift(ty);
1268                    }
1269                } else {
1270                    // ... otherwise argument is read in succession from memory
1271                    // where the pointer to the arguments is the first argument
1272                    // to the function.
1273                    let mut offset = 0usize;
1274                    self.emit(&Instruction::GetArg { nth: 0 });
1275                    let ptr = self.stack.pop().unwrap();
1276                    for (_, ty) in func.params.iter() {
1277                        offset = align_to(offset, self.bindgen.sizes().align(ty));
1278                        self.read_from_memory(ty, ptr.clone(), offset as i32);
1279                        offset += self.bindgen.sizes().size(ty);
1280                    }
1281                }
1282
1283                // ... and that allows us to call the interface types function
1284                self.emit(&Instruction::CallInterface {
1285                    module: &self.iface.name,
1286                    func,
1287                });
1288
1289                // This was dynamically allocated by the caller so after
1290                // it's been read by the guest we need to deallocate it.
1291                if let AbiVariant::GuestExport = self.variant {
1292                    if sig.indirect_params {
1293                        let (size, align) = self
1294                            .bindgen
1295                            .sizes()
1296                            .record(func.params.iter().map(|t| &t.1));
1297                        self.emit(&Instruction::GetArg { nth: 0 });
1298                        self.emit(&Instruction::Free {
1299                            free: "canonical_abi_free",
1300                            size,
1301                            align,
1302                        });
1303                    }
1304                }
1305
1306                if func.is_async {
1307                    match self.variant {
1308                        // Returning from a guest import means that the
1309                        // completion callback needs to be called which is
1310                        // currently given the lowered representation of the
1311                        // result.
1312                        AbiVariant::GuestImport => {
1313                            self.lower(&func.result);
1314
1315                            let mut tys = Vec::new();
1316                            self.iface.push_wasm(self.variant, &func.result, &mut tys);
1317                            assert_eq!(self.stack.len(), tys.len());
1318                            let operands = mem::take(&mut self.stack);
1319                            // function index to call
1320                            self.emit(&Instruction::GetArg {
1321                                nth: sig.params.len() - 2,
1322                            });
1323                            // environment for the function
1324                            self.emit(&Instruction::GetArg {
1325                                nth: sig.params.len() - 1,
1326                            });
1327                            self.stack.extend(operands);
1328                            self.emit(&Instruction::ReturnAsyncImport {
1329                                func,
1330                                params: tys.len(),
1331                            });
1332                        }
1333
1334                        // Returning from a guest export means that we need to
1335                        // invoke the completion intrinsics with where the
1336                        // result is stored in linear memory.
1337                        AbiVariant::GuestExport => {
1338                            let size = self.bindgen.sizes().size(&func.result);
1339                            let align = self.bindgen.sizes().align(&func.result);
1340                            let ptr = self.bindgen.return_pointer(self.iface, size, align);
1341                            self.write_to_memory(&func.result, ptr.clone(), 0);
1342
1343                            // Get the caller's context index.
1344                            self.emit(&Instruction::GetArg {
1345                                nth: sig.params.len() - 1,
1346                            });
1347                            self.stack.push(ptr);
1348
1349                            // This will call the "done" function with the
1350                            // context/pointer argument
1351                            self.emit(&Instruction::ReturnAsyncExport { func });
1352                        }
1353                    }
1354                } else {
1355                    if !sig.retptr {
1356                        // With no return pointer in use we simply lower the
1357                        // result and return that directly from the function.
1358                        self.lower(&func.result);
1359                    } else {
1360                        match self.variant {
1361                            // When a function is imported to a guest this means
1362                            // it's a host providing the implementation of the
1363                            // import. The result is stored in the pointer
1364                            // specified in the last argument, so we get the
1365                            // pointer here and then write the return value into
1366                            // it.
1367                            AbiVariant::GuestImport => {
1368                                self.emit(&Instruction::GetArg {
1369                                    nth: sig.params.len() - 1,
1370                                });
1371                                let ptr = self.stack.pop().unwrap();
1372                                self.write_to_memory(&func.result, ptr, 0);
1373                            }
1374
1375                            // For a guest import this is a function defined in
1376                            // wasm, so we're returning a pointer where the
1377                            // value was stored at. Allocate some space here
1378                            // (statically) and then write the result into that
1379                            // memory, returning the pointer at the end.
1380                            AbiVariant::GuestExport => {
1381                                let size = self.bindgen.sizes().size(&func.result);
1382                                let align = self.bindgen.sizes().align(&func.result);
1383                                let ptr = self.bindgen.return_pointer(self.iface, size, align);
1384                                self.write_to_memory(&func.result, ptr.clone(), 0);
1385                                self.stack.push(ptr);
1386                            }
1387                        }
1388                    }
1389
1390                    self.emit(&Instruction::Return {
1391                        func,
1392                        amt: sig.results.len(),
1393                    });
1394                }
1395            }
1396        }
1397
1398        assert!(
1399            self.stack.is_empty(),
1400            "stack has {} items remaining",
1401            self.stack.len()
1402        );
1403    }
1404
1405    fn emit(&mut self, inst: &Instruction<'_>) {
1406        self.operands.clear();
1407        self.results.clear();
1408
1409        let operands_len = inst.operands_len();
1410        assert!(
1411            self.stack.len() >= operands_len,
1412            "not enough operands on stack for {:?}",
1413            inst
1414        );
1415        self.operands
1416            .extend(self.stack.drain((self.stack.len() - operands_len)..));
1417        self.results.reserve(inst.results_len());
1418
1419        self.bindgen
1420            .emit(self.iface, inst, &mut self.operands, &mut self.results);
1421
1422        assert_eq!(
1423            self.results.len(),
1424            inst.results_len(),
1425            "{:?} expected {} results, got {}",
1426            inst,
1427            inst.results_len(),
1428            self.results.len()
1429        );
1430        self.stack.append(&mut self.results);
1431    }
1432
1433    fn push_block(&mut self) {
1434        self.bindgen.push_block();
1435    }
1436
1437    fn finish_block(&mut self, size: usize) {
1438        self.operands.clear();
1439        assert!(
1440            size <= self.stack.len(),
1441            "not enough operands on stack for finishing block",
1442        );
1443        self.operands
1444            .extend(self.stack.drain((self.stack.len() - size)..));
1445        self.bindgen.finish_block(&mut self.operands);
1446    }
1447
1448    fn lower(&mut self, ty: &Type) {
1449        use Instruction::*;
1450
1451        match *ty {
1452            Type::Unit => self.emit(&UnitLower),
1453            Type::Bool => self.emit(&I32FromBool),
1454            Type::S8 => self.emit(&I32FromS8),
1455            Type::U8 => self.emit(&I32FromU8),
1456            Type::S16 => self.emit(&I32FromS16),
1457            Type::U16 => self.emit(&I32FromU16),
1458            Type::S32 => self.emit(&I32FromS32),
1459            Type::U32 => self.emit(&I32FromU32),
1460            Type::S64 => self.emit(&I64FromS64),
1461            Type::U64 => self.emit(&I64FromU64),
1462            Type::Char => self.emit(&I32FromChar),
1463            Type::Float32 => self.emit(&F32FromFloat32),
1464            Type::Float64 => self.emit(&F64FromFloat64),
1465            Type::Handle(ty) => {
1466                let borrowed = match self.lift_lower {
1467                    // This means that a return value is being lowered, which is
1468                    // never borrowed.
1469                    LiftLower::LiftArgsLowerResults => false,
1470                    // There's one of three possible situations we're in:
1471                    //
1472                    // * The handle is defined by the wasm module itself. This
1473                    //   is the only actual possible scenario today due to how
1474                    //   witx is defined. In this situation the handle is owned
1475                    //   by the host and "proof of ownership" is being offered
1476                    //   and there's no need to relinquish ownership.
1477                    //
1478                    // * The handle is defined by the host, and it's passing it
1479                    //   to a wasm module. This should use an owned conversion.
1480                    //   This isn't expressible in today's `*.witx` format.
1481                    //
1482                    // * The handle is defined by neither the host or the wasm
1483                    //   mdoule. This means that the host is passing a
1484                    //   capability from another wasm module into this one,
1485                    //   meaning it's doing so by reference since the host is
1486                    //   retaining access to its own
1487                    //
1488                    // Note, again, only the first bullet here is possible
1489                    // today, hence the hardcoded `true` value. We'll need to
1490                    // refactor `witx` to expose the other possibilities.
1491                    LiftLower::LowerArgsLiftResults => true,
1492                };
1493                if borrowed {
1494                    self.emit(&I32FromBorrowedHandle { ty });
1495                } else {
1496                    self.emit(&I32FromOwnedHandle { ty });
1497                }
1498            }
1499            Type::String => {
1500                let realloc = self.list_realloc();
1501                self.emit(&StringLower { realloc });
1502            }
1503            Type::Id(id) => match &self.iface.types[id].kind {
1504                TypeDefKind::Type(t) => self.lower(t),
1505                TypeDefKind::List(element) => {
1506                    let realloc = self.list_realloc();
1507                    if self.bindgen.is_list_canonical(self.iface, element) {
1508                        self.emit(&ListCanonLower { element, realloc });
1509                    } else {
1510                        self.push_block();
1511                        self.emit(&IterElem { element });
1512                        self.emit(&IterBasePointer);
1513                        let addr = self.stack.pop().unwrap();
1514                        self.write_to_memory(element, addr, 0);
1515                        self.finish_block(0);
1516                        self.emit(&ListLower { element, realloc });
1517                    }
1518                }
1519                TypeDefKind::Record(record) => {
1520                    self.emit(&RecordLower {
1521                        record,
1522                        ty: id,
1523                        name: self.iface.types[id].name.as_deref().unwrap(),
1524                    });
1525                    let values = self
1526                        .stack
1527                        .drain(self.stack.len() - record.fields.len()..)
1528                        .collect::<Vec<_>>();
1529                    for (field, value) in record.fields.iter().zip(values) {
1530                        self.stack.push(value);
1531                        self.lower(&field.ty);
1532                    }
1533                }
1534                TypeDefKind::Tuple(tuple) => {
1535                    self.emit(&TupleLower { tuple, ty: id });
1536                    let values = self
1537                        .stack
1538                        .drain(self.stack.len() - tuple.types.len()..)
1539                        .collect::<Vec<_>>();
1540                    for (ty, value) in tuple.types.iter().zip(values) {
1541                        self.stack.push(value);
1542                        self.lower(ty);
1543                    }
1544                }
1545
1546                TypeDefKind::Flags(flags) => {
1547                    self.emit(&FlagsLower {
1548                        flags,
1549                        ty: id,
1550                        name: self.iface.types[id].name.as_ref().unwrap(),
1551                    });
1552                }
1553
1554                TypeDefKind::Variant(v) => {
1555                    let results = self.lower_variant_arms(ty, v.cases.iter().map(|c| &c.ty));
1556                    self.emit(&VariantLower {
1557                        variant: v,
1558                        ty: id,
1559                        results: &results,
1560                        name: self.iface.types[id].name.as_deref().unwrap(),
1561                    });
1562                }
1563                TypeDefKind::Enum(enum_) => {
1564                    self.emit(&EnumLower {
1565                        enum_,
1566                        ty: id,
1567                        name: self.iface.types[id].name.as_deref().unwrap(),
1568                    });
1569                }
1570                TypeDefKind::Option(t) => {
1571                    let results = self.lower_variant_arms(ty, [&Type::Unit, t]);
1572                    self.emit(&OptionLower {
1573                        payload: t,
1574                        ty: id,
1575                        results: &results,
1576                    });
1577                }
1578                TypeDefKind::Expected(e) => {
1579                    let results = self.lower_variant_arms(ty, [&e.ok, &e.err]);
1580                    self.emit(&ExpectedLower {
1581                        expected: e,
1582                        ty: id,
1583                        results: &results,
1584                    });
1585                }
1586                TypeDefKind::Union(union) => {
1587                    let results = self.lower_variant_arms(ty, union.cases.iter().map(|c| &c.ty));
1588                    self.emit(&UnionLower {
1589                        union,
1590                        ty: id,
1591                        results: &results,
1592                        name: self.iface.types[id].name.as_deref().unwrap(),
1593                    });
1594                }
1595                TypeDefKind::Future(_) => todo!("lower future"),
1596                TypeDefKind::Stream(_) => todo!("lower stream"),
1597            },
1598        }
1599    }
1600
1601    fn lower_variant_arms<'b>(
1602        &mut self,
1603        ty: &Type,
1604        cases: impl IntoIterator<Item = &'b Type>,
1605    ) -> Vec<WasmType> {
1606        use Instruction::*;
1607        let mut results = Vec::new();
1608        let mut temp = Vec::new();
1609        let mut casts = Vec::new();
1610        self.iface.push_wasm(self.variant, ty, &mut results);
1611        for (i, ty) in cases.into_iter().enumerate() {
1612            self.push_block();
1613            self.emit(&VariantPayloadName);
1614            let payload_name = self.stack.pop().unwrap();
1615            self.emit(&I32Const { val: i as i32 });
1616            let mut pushed = 1;
1617            // Using the payload of this block we lower the type to
1618            // raw wasm values.
1619            self.stack.push(payload_name.clone());
1620            self.lower(ty);
1621
1622            // Determine the types of all the wasm values we just
1623            // pushed, and record how many. If we pushed too few
1624            // then we'll need to push some zeros after this.
1625            temp.truncate(0);
1626            self.iface.push_wasm(self.variant, ty, &mut temp);
1627            pushed += temp.len();
1628
1629            // For all the types pushed we may need to insert some
1630            // bitcasts. This will go through and cast everything
1631            // to the right type to ensure all blocks produce the
1632            // same set of results.
1633            casts.truncate(0);
1634            for (actual, expected) in temp.iter().zip(&results[1..]) {
1635                casts.push(cast(*actual, *expected));
1636            }
1637            if casts.iter().any(|c| *c != Bitcast::None) {
1638                self.emit(&Bitcasts { casts: &casts });
1639            }
1640
1641            // If we haven't pushed enough items in this block to match
1642            // what other variants are pushing then we need to push
1643            // some zeros.
1644            if pushed < results.len() {
1645                self.emit(&ConstZero {
1646                    tys: &results[pushed..],
1647                });
1648            }
1649            self.finish_block(results.len());
1650        }
1651        results
1652    }
1653
1654    fn list_realloc(&self) -> Option<&'static str> {
1655        // Lowering parameters calling a wasm import means
1656        // we don't need to pass ownership, but we pass
1657        // ownership in all other cases.
1658        match (self.variant, self.lift_lower) {
1659            (AbiVariant::GuestImport, LiftLower::LowerArgsLiftResults) => None,
1660            _ => Some("canonical_abi_realloc"),
1661        }
1662    }
1663
1664    /// Note that in general everything in this function is the opposite of the
1665    /// `lower` function above. This is intentional and should be kept this way!
1666    fn lift(&mut self, ty: &Type) {
1667        use Instruction::*;
1668
1669        match *ty {
1670            Type::Unit => self.emit(&UnitLift),
1671            Type::Bool => self.emit(&BoolFromI32),
1672            Type::S8 => self.emit(&S8FromI32),
1673            Type::U8 => self.emit(&U8FromI32),
1674            Type::S16 => self.emit(&S16FromI32),
1675            Type::U16 => self.emit(&U16FromI32),
1676            Type::S32 => self.emit(&S32FromI32),
1677            Type::U32 => self.emit(&U32FromI32),
1678            Type::S64 => self.emit(&S64FromI64),
1679            Type::U64 => self.emit(&U64FromI64),
1680            Type::Char => self.emit(&CharFromI32),
1681            Type::Float32 => self.emit(&Float32FromF32),
1682            Type::Float64 => self.emit(&Float64FromF64),
1683            Type::Handle(ty) => {
1684                // For more information on these values see the comments in
1685                // `lower` above.
1686                let borrowed = match self.lift_lower {
1687                    LiftLower::LiftArgsLowerResults => true,
1688                    LiftLower::LowerArgsLiftResults => false,
1689                };
1690                if borrowed {
1691                    self.emit(&HandleBorrowedFromI32 { ty });
1692                } else {
1693                    self.emit(&HandleOwnedFromI32 { ty });
1694                }
1695            }
1696            Type::String => {
1697                let free = self.list_free();
1698                self.emit(&StringLift { free });
1699            }
1700            Type::Id(id) => match &self.iface.types[id].kind {
1701                TypeDefKind::Type(t) => self.lift(t),
1702                TypeDefKind::List(element) => {
1703                    let free = self.list_free();
1704                    if self.is_char(element) || self.bindgen.is_list_canonical(self.iface, element)
1705                    {
1706                        self.emit(&ListCanonLift {
1707                            element,
1708                            free,
1709                            ty: id,
1710                        });
1711                    } else {
1712                        self.push_block();
1713                        self.emit(&IterBasePointer);
1714                        let addr = self.stack.pop().unwrap();
1715                        self.read_from_memory(element, addr, 0);
1716                        self.finish_block(1);
1717                        self.emit(&ListLift {
1718                            element,
1719                            free,
1720                            ty: id,
1721                        });
1722                    }
1723                }
1724                TypeDefKind::Record(record) => {
1725                    let mut temp = Vec::new();
1726                    self.iface.push_wasm(self.variant, ty, &mut temp);
1727                    let mut args = self
1728                        .stack
1729                        .drain(self.stack.len() - temp.len()..)
1730                        .collect::<Vec<_>>();
1731                    for field in record.fields.iter() {
1732                        temp.truncate(0);
1733                        self.iface.push_wasm(self.variant, &field.ty, &mut temp);
1734                        self.stack.extend(args.drain(..temp.len()));
1735                        self.lift(&field.ty);
1736                    }
1737                    self.emit(&RecordLift {
1738                        record,
1739                        ty: id,
1740                        name: self.iface.types[id].name.as_deref().unwrap(),
1741                    });
1742                }
1743                TypeDefKind::Tuple(tuple) => {
1744                    let mut temp = Vec::new();
1745                    self.iface.push_wasm(self.variant, ty, &mut temp);
1746                    let mut args = self
1747                        .stack
1748                        .drain(self.stack.len() - temp.len()..)
1749                        .collect::<Vec<_>>();
1750                    for ty in tuple.types.iter() {
1751                        temp.truncate(0);
1752                        self.iface.push_wasm(self.variant, ty, &mut temp);
1753                        self.stack.extend(args.drain(..temp.len()));
1754                        self.lift(ty);
1755                    }
1756                    self.emit(&TupleLift { tuple, ty: id });
1757                }
1758                TypeDefKind::Flags(flags) => {
1759                    self.emit(&FlagsLift {
1760                        flags,
1761                        ty: id,
1762                        name: self.iface.types[id].name.as_ref().unwrap(),
1763                    });
1764                }
1765
1766                TypeDefKind::Variant(v) => {
1767                    self.lift_variant_arms(ty, v.cases.iter().map(|c| &c.ty));
1768                    self.emit(&VariantLift {
1769                        variant: v,
1770                        ty: id,
1771                        name: self.iface.types[id].name.as_deref().unwrap(),
1772                    });
1773                }
1774
1775                TypeDefKind::Enum(enum_) => {
1776                    self.emit(&EnumLift {
1777                        enum_,
1778                        ty: id,
1779                        name: self.iface.types[id].name.as_deref().unwrap(),
1780                    });
1781                }
1782
1783                TypeDefKind::Option(t) => {
1784                    self.lift_variant_arms(ty, [&Type::Unit, t]);
1785                    self.emit(&OptionLift { payload: t, ty: id });
1786                }
1787
1788                TypeDefKind::Expected(e) => {
1789                    self.lift_variant_arms(ty, [&e.ok, &e.err]);
1790                    self.emit(&ExpectedLift {
1791                        expected: e,
1792                        ty: id,
1793                    });
1794                }
1795
1796                TypeDefKind::Union(union) => {
1797                    self.lift_variant_arms(ty, union.cases.iter().map(|c| &c.ty));
1798                    self.emit(&UnionLift {
1799                        union,
1800                        ty: id,
1801                        name: self.iface.types[id].name.as_deref().unwrap(),
1802                    });
1803                }
1804
1805                TypeDefKind::Future(_) => todo!("lift future"),
1806                TypeDefKind::Stream(_) => todo!("lift stream"),
1807            },
1808        }
1809    }
1810
1811    fn lift_variant_arms<'b>(&mut self, ty: &Type, cases: impl IntoIterator<Item = &'b Type>) {
1812        let mut params = Vec::new();
1813        let mut temp = Vec::new();
1814        let mut casts = Vec::new();
1815        self.iface.push_wasm(self.variant, ty, &mut params);
1816        let block_inputs = self
1817            .stack
1818            .drain(self.stack.len() + 1 - params.len()..)
1819            .collect::<Vec<_>>();
1820        for ty in cases {
1821            self.push_block();
1822            // Push only the values we need for this variant onto
1823            // the stack.
1824            temp.truncate(0);
1825            self.iface.push_wasm(self.variant, ty, &mut temp);
1826            self.stack
1827                .extend(block_inputs[..temp.len()].iter().cloned());
1828
1829            // Cast all the types we have on the stack to the actual
1830            // types needed for this variant, if necessary.
1831            casts.truncate(0);
1832            for (actual, expected) in temp.iter().zip(&params[1..]) {
1833                casts.push(cast(*expected, *actual));
1834            }
1835            if casts.iter().any(|c| *c != Bitcast::None) {
1836                self.emit(&Instruction::Bitcasts { casts: &casts });
1837            }
1838
1839            // Then recursively lift this variant's payload.
1840            self.lift(ty);
1841            self.finish_block(1);
1842        }
1843    }
1844
1845    fn list_free(&self) -> Option<&'static str> {
1846        // Lifting the arguments of a defined import means that, if
1847        // possible, the caller still retains ownership and we don't
1848        // free anything.
1849        match (self.variant, self.lift_lower) {
1850            (AbiVariant::GuestImport, LiftLower::LiftArgsLowerResults) => None,
1851            _ => Some("canonical_abi_free"),
1852        }
1853    }
1854
1855    fn write_to_memory(&mut self, ty: &Type, addr: B::Operand, offset: i32) {
1856        use Instruction::*;
1857
1858        match *ty {
1859            Type::Unit => self.lower(ty),
1860            // Builtin types need different flavors of storage instructions
1861            // depending on the size of the value written.
1862            Type::Bool | Type::U8 | Type::S8 => {
1863                self.lower_and_emit(ty, addr, &I32Store8 { offset })
1864            }
1865            Type::U16 | Type::S16 => self.lower_and_emit(ty, addr, &I32Store16 { offset }),
1866            Type::U32 | Type::S32 | Type::Handle(_) | Type::Char => {
1867                self.lower_and_emit(ty, addr, &I32Store { offset })
1868            }
1869            Type::U64 | Type::S64 => self.lower_and_emit(ty, addr, &I64Store { offset }),
1870            Type::Float32 => self.lower_and_emit(ty, addr, &F32Store { offset }),
1871            Type::Float64 => self.lower_and_emit(ty, addr, &F64Store { offset }),
1872            Type::String => self.write_list_to_memory(ty, addr, offset),
1873
1874            Type::Id(id) => match &self.iface.types[id].kind {
1875                TypeDefKind::Type(t) => self.write_to_memory(t, addr, offset),
1876                TypeDefKind::List(_) => self.write_list_to_memory(ty, addr, offset),
1877
1878                // Decompose the record into its components and then write all
1879                // the components into memory one-by-one.
1880                TypeDefKind::Record(record) => {
1881                    self.emit(&RecordLower {
1882                        record,
1883                        ty: id,
1884                        name: self.iface.types[id].name.as_deref().unwrap(),
1885                    });
1886                    self.write_fields_to_memory(
1887                        &record.fields.iter().map(|f| f.ty).collect::<Vec<_>>(),
1888                        addr,
1889                        offset,
1890                    );
1891                }
1892                TypeDefKind::Tuple(tuple) => {
1893                    self.emit(&TupleLower { tuple, ty: id });
1894                    self.write_fields_to_memory(&tuple.types, addr, offset);
1895                }
1896
1897                TypeDefKind::Flags(f) => {
1898                    self.lower(ty);
1899                    match f.repr() {
1900                        FlagsRepr::U8 => {
1901                            self.stack.push(addr);
1902                            self.store_intrepr(offset, Int::U8);
1903                        }
1904                        FlagsRepr::U16 => {
1905                            self.stack.push(addr);
1906                            self.store_intrepr(offset, Int::U16);
1907                        }
1908                        FlagsRepr::U32(n) => {
1909                            for i in (0..n).rev() {
1910                                self.stack.push(addr.clone());
1911                                self.emit(&I32Store {
1912                                    offset: offset + (i as i32) * 4,
1913                                });
1914                            }
1915                        }
1916                    }
1917                }
1918
1919                // Each case will get its own block, and the first item in each
1920                // case is writing the discriminant. After that if we have a
1921                // payload we write the payload after the discriminant, aligned up
1922                // to the type's alignment.
1923                TypeDefKind::Variant(v) => {
1924                    self.write_variant_arms_to_memory(
1925                        offset,
1926                        addr,
1927                        v.tag(),
1928                        v.cases.iter().map(|c| &c.ty),
1929                    );
1930                    self.emit(&VariantLower {
1931                        variant: v,
1932                        ty: id,
1933                        results: &[],
1934                        name: self.iface.types[id].name.as_deref().unwrap(),
1935                    });
1936                }
1937
1938                TypeDefKind::Option(t) => {
1939                    self.write_variant_arms_to_memory(offset, addr, Int::U8, [&Type::Unit, t]);
1940                    self.emit(&OptionLower {
1941                        payload: t,
1942                        ty: id,
1943                        results: &[],
1944                    });
1945                }
1946
1947                TypeDefKind::Expected(e) => {
1948                    self.write_variant_arms_to_memory(offset, addr, Int::U8, [&e.ok, &e.err]);
1949                    self.emit(&ExpectedLower {
1950                        expected: e,
1951                        ty: id,
1952                        results: &[],
1953                    });
1954                }
1955
1956                TypeDefKind::Enum(e) => {
1957                    self.lower(ty);
1958                    self.stack.push(addr);
1959                    self.store_intrepr(offset, e.tag());
1960                }
1961
1962                TypeDefKind::Union(union) => {
1963                    self.write_variant_arms_to_memory(
1964                        offset,
1965                        addr,
1966                        union.tag(),
1967                        union.cases.iter().map(|c| &c.ty),
1968                    );
1969                    self.emit(&UnionLower {
1970                        union,
1971                        ty: id,
1972                        results: &[],
1973                        name: self.iface.types[id].name.as_deref().unwrap(),
1974                    });
1975                }
1976
1977                TypeDefKind::Future(_) => todo!("write future to memory"),
1978                TypeDefKind::Stream(_) => todo!("write stream to memory"),
1979            },
1980        }
1981    }
1982
1983    fn write_variant_arms_to_memory<'b>(
1984        &mut self,
1985        offset: i32,
1986        addr: B::Operand,
1987        tag: Int,
1988        cases: impl IntoIterator<Item = &'b Type> + Clone,
1989    ) {
1990        let payload_offset =
1991            offset + (self.bindgen.sizes().payload_offset(tag, cases.clone()) as i32);
1992        for (i, ty) in cases.into_iter().enumerate() {
1993            self.push_block();
1994            self.emit(&Instruction::VariantPayloadName);
1995            let payload_name = self.stack.pop().unwrap();
1996            self.emit(&Instruction::I32Const { val: i as i32 });
1997            self.stack.push(addr.clone());
1998            self.store_intrepr(offset, tag);
1999            self.stack.push(payload_name.clone());
2000            self.write_to_memory(ty, addr.clone(), payload_offset);
2001            self.finish_block(0);
2002        }
2003    }
2004
2005    fn write_list_to_memory(&mut self, ty: &Type, addr: B::Operand, offset: i32) {
2006        // After lowering the list there's two i32 values on the stack
2007        // which we write into memory, writing the pointer into the low address
2008        // and the length into the high address.
2009        self.lower(ty);
2010        self.stack.push(addr.clone());
2011        self.emit(&Instruction::I32Store { offset: offset + 4 });
2012        self.stack.push(addr);
2013        self.emit(&Instruction::I32Store { offset });
2014    }
2015
2016    fn write_fields_to_memory(&mut self, tys: &[Type], addr: B::Operand, offset: i32) {
2017        let fields = self
2018            .stack
2019            .drain(self.stack.len() - tys.len()..)
2020            .collect::<Vec<_>>();
2021        for ((field_offset, op), ty) in self
2022            .bindgen
2023            .sizes()
2024            .field_offsets(tys.iter())
2025            .into_iter()
2026            .zip(fields)
2027            .zip(tys)
2028        {
2029            self.stack.push(op);
2030            self.write_to_memory(ty, addr.clone(), offset + (field_offset as i32));
2031        }
2032    }
2033
2034    fn lower_and_emit(&mut self, ty: &Type, addr: B::Operand, instr: &Instruction) {
2035        self.lower(ty);
2036        self.stack.push(addr);
2037        self.emit(instr);
2038    }
2039
2040    fn read_from_memory(&mut self, ty: &Type, addr: B::Operand, offset: i32) {
2041        use Instruction::*;
2042
2043        match *ty {
2044            Type::Unit => self.emit(&UnitLift),
2045            Type::Bool => self.emit_and_lift(ty, addr, &I32Load8U { offset }),
2046            Type::U8 => self.emit_and_lift(ty, addr, &I32Load8U { offset }),
2047            Type::S8 => self.emit_and_lift(ty, addr, &I32Load8S { offset }),
2048            Type::U16 => self.emit_and_lift(ty, addr, &I32Load16U { offset }),
2049            Type::S16 => self.emit_and_lift(ty, addr, &I32Load16S { offset }),
2050            Type::U32 | Type::S32 | Type::Char | Type::Handle(_) => {
2051                self.emit_and_lift(ty, addr, &I32Load { offset })
2052            }
2053            Type::U64 | Type::S64 => self.emit_and_lift(ty, addr, &I64Load { offset }),
2054            Type::Float32 => self.emit_and_lift(ty, addr, &F32Load { offset }),
2055            Type::Float64 => self.emit_and_lift(ty, addr, &F64Load { offset }),
2056            Type::String => self.read_list_from_memory(ty, addr, offset),
2057
2058            Type::Id(id) => match &self.iface.types[id].kind {
2059                TypeDefKind::Type(t) => self.read_from_memory(t, addr, offset),
2060
2061                TypeDefKind::List(_) => self.read_list_from_memory(ty, addr, offset),
2062
2063                // Read and lift each field individually, adjusting the offset
2064                // as we go along, then aggregate all the fields into the
2065                // record.
2066                TypeDefKind::Record(record) => {
2067                    self.read_fields_from_memory(
2068                        &record.fields.iter().map(|f| f.ty).collect::<Vec<_>>(),
2069                        addr,
2070                        offset,
2071                    );
2072                    self.emit(&RecordLift {
2073                        record,
2074                        ty: id,
2075                        name: self.iface.types[id].name.as_deref().unwrap(),
2076                    });
2077                }
2078                TypeDefKind::Tuple(tuple) => {
2079                    self.read_fields_from_memory(&tuple.types, addr, offset);
2080                    self.emit(&TupleLift { tuple, ty: id });
2081                }
2082
2083                TypeDefKind::Flags(f) => {
2084                    match f.repr() {
2085                        FlagsRepr::U8 => {
2086                            self.stack.push(addr);
2087                            self.load_intrepr(offset, Int::U8);
2088                        }
2089                        FlagsRepr::U16 => {
2090                            self.stack.push(addr);
2091                            self.load_intrepr(offset, Int::U16);
2092                        }
2093                        FlagsRepr::U32(n) => {
2094                            for i in 0..n {
2095                                self.stack.push(addr.clone());
2096                                self.emit(&I32Load {
2097                                    offset: offset + (i as i32) * 4,
2098                                });
2099                            }
2100                        }
2101                    }
2102                    self.lift(ty);
2103                }
2104
2105                // Each case will get its own block, and we'll dispatch to the
2106                // right block based on the `i32.load` we initially perform. Each
2107                // individual block is pretty simple and just reads the payload type
2108                // from the corresponding offset if one is available.
2109                TypeDefKind::Variant(variant) => {
2110                    self.read_variant_arms_from_memory(
2111                        offset,
2112                        addr,
2113                        variant.tag(),
2114                        variant.cases.iter().map(|c| &c.ty),
2115                    );
2116                    self.emit(&VariantLift {
2117                        variant,
2118                        ty: id,
2119                        name: self.iface.types[id].name.as_deref().unwrap(),
2120                    });
2121                }
2122
2123                TypeDefKind::Option(t) => {
2124                    self.read_variant_arms_from_memory(offset, addr, Int::U8, [&Type::Unit, t]);
2125                    self.emit(&OptionLift { payload: t, ty: id });
2126                }
2127
2128                TypeDefKind::Expected(e) => {
2129                    self.read_variant_arms_from_memory(offset, addr, Int::U8, [&e.ok, &e.err]);
2130                    self.emit(&ExpectedLift {
2131                        expected: e,
2132                        ty: id,
2133                    });
2134                }
2135
2136                TypeDefKind::Enum(e) => {
2137                    self.stack.push(addr.clone());
2138                    self.load_intrepr(offset, e.tag());
2139                    self.lift(ty);
2140                }
2141
2142                TypeDefKind::Union(union) => {
2143                    self.read_variant_arms_from_memory(
2144                        offset,
2145                        addr,
2146                        union.tag(),
2147                        union.cases.iter().map(|c| &c.ty),
2148                    );
2149                    self.emit(&UnionLift {
2150                        union,
2151                        ty: id,
2152                        name: self.iface.types[id].name.as_deref().unwrap(),
2153                    });
2154                }
2155
2156                TypeDefKind::Future(_) => todo!("read future from memory"),
2157                TypeDefKind::Stream(_) => todo!("read stream from memory"),
2158            },
2159        }
2160    }
2161
2162    fn read_variant_arms_from_memory<'b>(
2163        &mut self,
2164        offset: i32,
2165        addr: B::Operand,
2166        tag: Int,
2167        cases: impl IntoIterator<Item = &'b Type> + Clone,
2168    ) {
2169        self.stack.push(addr.clone());
2170        self.load_intrepr(offset, tag);
2171        let payload_offset =
2172            offset + (self.bindgen.sizes().payload_offset(tag, cases.clone()) as i32);
2173        for ty in cases {
2174            self.push_block();
2175            self.read_from_memory(ty, addr.clone(), payload_offset);
2176            self.finish_block(1);
2177        }
2178    }
2179
2180    fn read_list_from_memory(&mut self, ty: &Type, addr: B::Operand, offset: i32) {
2181        // Read the pointer/len and then perform the standard lifting
2182        // proceses.
2183        self.stack.push(addr.clone());
2184        self.emit(&Instruction::I32Load { offset });
2185        self.stack.push(addr);
2186        self.emit(&Instruction::I32Load { offset: offset + 4 });
2187        self.lift(ty);
2188    }
2189
2190    fn read_fields_from_memory(&mut self, tys: &[Type], addr: B::Operand, offset: i32) {
2191        for (field_offset, ty) in self.bindgen.sizes().field_offsets(tys).into_iter().zip(tys) {
2192            self.read_from_memory(ty, addr.clone(), offset + (field_offset as i32));
2193        }
2194    }
2195
2196    fn emit_and_lift(&mut self, ty: &Type, addr: B::Operand, instr: &Instruction) {
2197        self.stack.push(addr);
2198        self.emit(instr);
2199        self.lift(ty);
2200    }
2201
2202    fn load_intrepr(&mut self, offset: i32, repr: Int) {
2203        self.emit(&match repr {
2204            Int::U64 => Instruction::I64Load { offset },
2205            Int::U32 => Instruction::I32Load { offset },
2206            Int::U16 => Instruction::I32Load16U { offset },
2207            Int::U8 => Instruction::I32Load8U { offset },
2208        });
2209    }
2210
2211    fn store_intrepr(&mut self, offset: i32, repr: Int) {
2212        self.emit(&match repr {
2213            Int::U64 => Instruction::I64Store { offset },
2214            Int::U32 => Instruction::I32Store { offset },
2215            Int::U16 => Instruction::I32Store16 { offset },
2216            Int::U8 => Instruction::I32Store8 { offset },
2217        });
2218    }
2219
2220    fn is_char(&self, ty: &Type) -> bool {
2221        match ty {
2222            Type::Char => true,
2223            Type::Id(id) => match &self.iface.types[*id].kind {
2224                TypeDefKind::Type(t) => self.is_char(t),
2225                _ => false,
2226            },
2227            _ => false,
2228        }
2229    }
2230}
2231
2232fn cast(from: WasmType, to: WasmType) -> Bitcast {
2233    use WasmType::*;
2234
2235    match (from, to) {
2236        (I32, I32) | (I64, I64) | (F32, F32) | (F64, F64) => Bitcast::None,
2237
2238        (I32, I64) => Bitcast::I32ToI64,
2239        (F32, I32) => Bitcast::F32ToI32,
2240        (F64, I64) => Bitcast::F64ToI64,
2241
2242        (I64, I32) => Bitcast::I64ToI32,
2243        (I32, F32) => Bitcast::I32ToF32,
2244        (I64, F64) => Bitcast::I64ToF64,
2245
2246        (F32, I64) => Bitcast::F32ToI64,
2247        (I64, F32) => Bitcast::I64ToF32,
2248
2249        (F32, F64) | (F64, F32) | (F64, I32) | (I32, F64) => unreachable!(),
2250    }
2251}