wit_text/
binary.rs

1use crate::ast::*;
2
3pub fn append(adapters: &[Adapter<'_>], wasm: &mut Vec<u8>) {
4    if adapters.len() == 0 {
5        return;
6    }
7    let mut types = Vec::new();
8    let mut imports = Vec::new();
9    let mut funcs = Vec::new();
10    let mut exports = Vec::new();
11    let mut implements = Vec::new();
12    for adapter in adapters {
13        match adapter {
14            Adapter::Type(i) => types.push(i),
15            Adapter::Import(i) => imports.push(i),
16            Adapter::Func(i) => funcs.push(i),
17            Adapter::Export(i) => exports.push(i),
18            Adapter::Implement(i) => implements.push(i),
19        }
20    }
21
22    let mut writer = wit_writer::Writer::new();
23
24    // First up is the type section ...
25    let mut w = writer.types(types.len() as u32);
26    for ty in types {
27        w.add(
28            ty.params.len() as u32,
29            |w| {
30                for (_, param) in ty.params.iter() {
31                    write_ty(w, param);
32                }
33            },
34            ty.results.len() as u32,
35            |w| {
36                for result in ty.results.iter() {
37                    write_ty(w, result);
38                }
39            },
40        );
41    }
42
43    drop(w);
44
45    // ... then the import section ...
46    let mut w = writer.imports(imports.len() as u32);
47    for import in imports {
48        w.add(
49            import.module,
50            import.name,
51            get_num(import.ty.index.as_ref().expect("unresolved type use")),
52        );
53    }
54    drop(w);
55
56    // ... then the function section ...
57    let mut w = writer.funcs(funcs.len() as u32);
58    for func in funcs {
59        let mut w = w.add(get_num(
60            &func.ty.index.as_ref().expect("unresolved type use"),
61        ));
62        assert!(func.export.is_none());
63        let instrs = match &func.kind {
64            FuncKind::Inline { instrs } => instrs,
65            FuncKind::Import { .. } => panic!("imports should be de-inlined"),
66        };
67        for instr in instrs.instrs.iter() {
68            use Instruction::*;
69
70            match instr {
71                ArgGet(a) => w.arg_get(get_num(a)),
72                CallCore(a) => w.call_core(get_num(a)),
73                DeferCallCore(a) => w.defer_call_core(get_num(a)),
74                CallAdapter(a) => w.call_adapter(get_num(a)),
75                MemoryToString(a) => w.memory_to_string(get_num(&a.mem)),
76                StringToMemory(a) => w.string_to_memory(get_num(&a.malloc), get_num(&a.mem)),
77
78                I32ToS8 => w.i32_to_s8(),
79                I32ToS8X => w.i32_to_s8x(),
80                I32ToU8 => w.i32_to_u8(),
81                I32ToS16 => w.i32_to_s16(),
82                I32ToS16X => w.i32_to_s16x(),
83                I32ToU16 => w.i32_to_u16(),
84                I32ToS32 => w.i32_to_s32(),
85                I32ToU32 => w.i32_to_u32(),
86                I32ToS64 => w.i32_to_s64(),
87                I32ToU64 => w.i32_to_u64(),
88
89                I64ToS8 => w.i64_to_s8(),
90                I64ToS8X => w.i64_to_s8x(),
91                I64ToU8 => w.i64_to_u8(),
92                I64ToS16 => w.i64_to_s16(),
93                I64ToS16X => w.i64_to_s16x(),
94                I64ToU16 => w.i64_to_u16(),
95                I64ToS32 => w.i64_to_s32(),
96                I64ToS32X => w.i64_to_s32x(),
97                I64ToU32 => w.i64_to_u32(),
98                I64ToS64 => w.i64_to_s64(),
99                I64ToU64 => w.i64_to_u64(),
100
101                S8ToI32 => w.s8_to_i32(),
102                U8ToI32 => w.u8_to_i32(),
103                S16ToI32 => w.s16_to_i32(),
104                U16ToI32 => w.u16_to_i32(),
105                S32ToI32 => w.s32_to_i32(),
106                U32ToI32 => w.u32_to_i32(),
107                S64ToI32 => w.s64_to_i32(),
108                S64ToI32X => w.s64_to_i32x(),
109                U64ToI32 => w.u64_to_i32(),
110                U64ToI32X => w.u64_to_i32x(),
111
112                S8ToI64 => w.s8_to_i64(),
113                U8ToI64 => w.u8_to_i64(),
114                S16ToI64 => w.s16_to_i64(),
115                U16ToI64 => w.u16_to_i64(),
116                S32ToI64 => w.s32_to_i64(),
117                U32ToI64 => w.u32_to_i64(),
118                S64ToI64 => w.s64_to_i64(),
119                U64ToI64 => w.u64_to_i64(),
120            }
121        }
122    }
123    drop(w);
124
125    // ... then the export section ...
126    let mut w = writer.exports(exports.len() as u32);
127    for export in exports {
128        w.add(export.name, get_num(&export.func));
129    }
130    drop(w);
131
132    // ... and finally the implements section
133    let mut w = writer.implements(implements.len() as u32);
134    for implement in implements {
135        let implemented = match &implement.implemented {
136            Implemented::ByIndex(i) => i,
137            Implemented::ByName { .. } => panic!("should be `ByIndex`"),
138        };
139        let implementation = match &implement.implementation {
140            Implementation::ByIndex(i) => i,
141            Implementation::Inline { .. } => panic!("should be `ByIndex`"),
142        };
143        w.add(get_num(implemented), get_num(implementation));
144    }
145    drop(w);
146
147    wasm.extend_from_slice(&writer.into_custom_section());
148}
149
150fn get_num(idx: &wast::Index<'_>) -> u32 {
151    match idx {
152        wast::Index::Num(n, _) => *n,
153        wast::Index::Id(s) => panic!("unresolved name: {}", s.name()),
154    }
155}
156
157fn write_ty(w: &mut wit_writer::Type<'_>, ty: &ValType) {
158    match ty {
159        ValType::S8 => w.s8(),
160        ValType::S16 => w.s16(),
161        ValType::S32 => w.s32(),
162        ValType::S64 => w.s64(),
163        ValType::U8 => w.u8(),
164        ValType::U16 => w.u16(),
165        ValType::U32 => w.u32(),
166        ValType::U64 => w.u64(),
167        ValType::F32 => w.f32(),
168        ValType::F64 => w.f64(),
169        ValType::String => w.string(),
170        ValType::Externref => w.externref(),
171        ValType::I32 => w.i32(),
172        ValType::I64 => w.i64(),
173    }
174}