linera_wit_parser/
abi.rs

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