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 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 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 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 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 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}