Coverage Report

Created: 2023-04-25 07:07

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