1use crate::ast as wat;
2use crate::source::{describe_position, TextSource};
3use std::collections::HashMap;
4use std::fmt;
5use std::mem;
6use wain_ast as wasm;
7
8#[cfg_attr(test, derive(Debug))]
9pub enum TransformErrorKind<'source> {
10 IdIsNotDefined {
11 id: &'source str,
12 what: &'static str,
13 },
14 IdAlreadyDefined {
15 id: &'source str,
16 idx: u32,
17 what: &'static str,
18 },
19 LabelAndIdMismatch {
20 label: Option<&'source str>,
21 id: &'source str,
22 },
23 FuncTypeMismatch {
24 left_params: Vec<wat::ValType>,
25 left_results: Vec<wat::ValType>,
26 right_params: Vec<wat::ValType>,
27 right_results: Vec<wat::ValType>,
28 },
29}
30
31#[cfg_attr(test, derive(Debug))]
32pub struct TransformError<'s> {
33 kind: TransformErrorKind<'s>,
34 offset: usize,
35 source: &'s str,
36}
37
38impl<'s> TransformError<'s> {
39 fn new(kind: TransformErrorKind<'s>, offset: usize, source: &'s str) -> Box<Self> {
40 Box::new(TransformError { kind, offset, source })
41 }
42
43 pub fn offset(&self) -> usize {
44 self.offset
45 }
46
47 pub fn source(&self) -> &'s str {
48 self.source
49 }
50}
51
52impl<'s> fmt::Display for TransformError<'s> {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 use TransformErrorKind::*;
55 match &self.kind {
56 IdIsNotDefined { id, what } => write!(f, "No identifier '{}' for {} is found", id, what)?,
57 IdAlreadyDefined { id, idx, what } => write!(
58 f,
59 "Identifier '{}' is already defined to be mapped to index {} for {}",
60 id, idx, what
61 )?,
62 LabelAndIdMismatch { label: Some(label), id } => write!(
63 f,
64 "in control instruction, label '{}' and identifier '{}' must be the same",
65 label, id
66 )?,
67 LabelAndIdMismatch { label: None, id } => write!(
68 f,
69 "in control instruction, no label specified but identifier '{}' is set",
70 id
71 )?,
72 FuncTypeMismatch {
73 left_params,
74 left_results,
75 right_params,
76 right_results,
77 } => {
78 fn write_type_seq(f: &mut fmt::Formatter<'_>, tys: &[wat::ValType]) -> fmt::Result {
79 f.write_str("[")?;
80 let mut tys = tys.iter();
81 if let Some(ty) = tys.next() {
82 write!(f, "{}", ty)?;
83 }
84 for ty in tys {
85 write!(f, " {}", ty)?;
86 }
87 f.write_str("]")
88 }
89 write!(f, "function type mismatch between ")?;
90 write_type_seq(f, left_params)?;
91 write!(f, " -> ")?;
92 write_type_seq(f, left_results)?;
93 write!(f, " and ")?;
94 write_type_seq(f, right_params)?;
95 write!(f, " -> ")?;
96 write_type_seq(f, right_results)?;
97 }
98 }
99
100 describe_position(f, self.source, self.offset)
101 }
102}
103
104type Result<'s, T> = ::std::result::Result<T, Box<TransformError<'s>>>;
105
106type Indices<'s> = HashMap<&'s str, u32>;
107
108struct LabelStack<'s> {
109 source: &'s str,
110 stack: Vec<Option<&'s str>>,
111}
112
113impl<'s> LabelStack<'s> {
114 fn new(source: &'s str) -> Self {
115 Self { source, stack: vec![] }
116 }
117
118 fn resolve(&self, idx: wat::Index<'s>, offset: usize) -> Result<'s, u32> {
119 match idx {
120 wat::Index::Num(idx) => Ok(idx),
121 wat::Index::Ident(id) => {
122 if let Some(u) = self.find(id) {
123 Ok(u)
124 } else {
125 Err(TransformError::new(
126 TransformErrorKind::IdIsNotDefined { id, what: "label" },
127 offset,
128 self.source,
129 ))
130 }
131 }
132 }
133 }
134
135 fn push(&mut self, label: Option<&'s str>, id: Option<&'s str>, offset: usize) -> Result<'s, ()> {
136 let label = match (label, id) {
137 (Some(label), Some(id)) if label == id => label,
138 (_, Some(id)) => {
139 return Err(TransformError::new(
142 TransformErrorKind::LabelAndIdMismatch { label, id },
143 offset,
144 self.source,
145 ));
146 }
147 (Some(label), None) => label,
148 (None, None) => {
149 self.stack.push(None);
150 return Ok(());
151 }
152 };
153
154 self.stack.push(Some(label));
161 Ok(())
162 }
163
164 fn pop(&mut self) {
165 let popped = self.stack.pop().is_some();
166 assert!(popped);
167 }
168
169 fn find(&self, label: &'s str) -> Option<u32> {
175 self.stack.iter().rev().enumerate().find_map(|(i, l)| match l {
176 Some(l) if *l == label => Some(i as u32),
177 _ => None,
178 })
179 }
180}
181
182struct Context<'s> {
183 source: &'s str,
184 type_indices: Indices<'s>,
185 func_indices: Indices<'s>,
186 table_indices: Indices<'s>,
187 mem_indices: Indices<'s>,
188 global_indices: Indices<'s>,
189 local_indices: Indices<'s>,
190 next_local_idx: u32,
191 label_stack: LabelStack<'s>,
192 implicit_type_uses: Vec<u32>,
193 types: Vec<wat::FuncType<'s>>,
194}
195
196impl<'s> Context<'s> {
197 fn resolve_index(
198 &self,
199 indices: &Indices,
200 idx: wat::Index<'s>,
201 offset: usize,
202 what: &'static str,
203 ) -> Result<'s, u32> {
204 match idx {
205 wat::Index::Num(i) => Ok(i),
206 wat::Index::Ident(id) => {
207 if let Some(idx) = indices.get(id) {
208 Ok(*idx)
209 } else {
210 Err(TransformError::new(
211 TransformErrorKind::IdIsNotDefined { id, what },
212 offset,
213 self.source,
214 ))
215 }
216 }
217 }
218 }
219
220 fn resolve_type_idx(&mut self, ty: wat::TypeUse<'s>, offset: usize) -> Result<'s, u32> {
221 match ty.idx {
222 wat::TypeIndex::Explicit(idx) => {
223 let idx = self.resolve_index(&self.type_indices, idx, offset, "type")?;
224 if idx as usize >= self.types.len() {
225 return Ok(idx);
226 }
227 let wat::FuncType { params, results, .. } = &self.types[idx as usize];
228 if ty.params.is_empty() && ty.results.is_empty()
229 || ty.params.iter().map(|p| p.ty).eq(params.iter().map(|p| p.ty))
230 && ty.results.iter().map(|r| r.ty).eq(results.iter().map(|r| r.ty))
231 {
232 Ok(idx)
233 } else {
234 Err(TransformError::new(
235 TransformErrorKind::FuncTypeMismatch {
236 left_params: ty.params.iter().map(|p| p.ty).collect(),
237 left_results: ty.results.iter().map(|p| p.ty).collect(),
238 right_params: params.iter().map(|p| p.ty).collect(),
239 right_results: results.iter().map(|p| p.ty).collect(),
240 },
241 offset,
242 self.source,
243 ))
244 }
245 }
246 wat::TypeIndex::Implicit(idx) => Ok(self.implicit_type_uses[idx as usize]),
247 }
248 }
249
250 fn resolve_func_idx(&self, idx: wat::Index<'s>, offset: usize) -> Result<'s, u32> {
251 self.resolve_index(&self.func_indices, idx, offset, "function")
252 }
253
254 fn resolve_table_idx(&self, idx: wat::Index<'s>, offset: usize) -> Result<'s, u32> {
255 self.resolve_index(&self.table_indices, idx, offset, "table")
256 }
257
258 fn resolve_mem_idx(&self, idx: wat::Index<'s>, offset: usize) -> Result<'s, u32> {
259 self.resolve_index(&self.mem_indices, idx, offset, "memory")
260 }
261
262 fn resolve_global_idx(&self, idx: wat::Index<'s>, offset: usize) -> Result<'s, u32> {
263 self.resolve_index(&self.global_indices, idx, offset, "global")
264 }
265
266 fn start_func_scope(&mut self) {
267 self.next_local_idx = 0;
268 self.local_indices.clear();
269 }
270
271 fn new_local_idx(&mut self, id: Option<&'s str>, offset: usize) -> Result<'s, u32> {
272 let idx = self.next_local_idx;
273 if let Some(id) = id {
274 if let Some(idx) = self.local_indices.insert(id, idx) {
275 return Err(TransformError::new(
276 TransformErrorKind::IdAlreadyDefined {
277 id,
278 idx,
279 what: "local variable",
280 },
281 offset,
282 self.source,
283 ));
284 }
285 }
286 self.next_local_idx += 1;
287 Ok(idx)
288 }
289
290 fn resolve_local_idx(&self, idx: wat::Index<'s>, offset: usize) -> Result<'s, u32> {
291 self.resolve_index(&self.local_indices, idx, offset, "local variable")
292 }
293}
294
295pub fn wat2wasm<'s>(mut parsed: wat::Parsed<'s>, source: &'s str) -> Result<'s, wasm::Root<'s, TextSource<'s>>> {
296 let mut ctx = Context {
297 source,
298 type_indices: parsed.type_indices,
299 func_indices: parsed.func_indices,
300 table_indices: parsed.table_indices,
301 mem_indices: parsed.mem_indices,
302 global_indices: parsed.global_indices,
303 local_indices: Indices::new(),
304 next_local_idx: 0,
305 label_stack: LabelStack::new(source),
306 implicit_type_uses: mem::take(&mut parsed.module.implicit_type_uses),
307 types: Vec::new(),
308 };
309 let module = parsed.module.transform(&mut ctx)?;
310 Ok(wasm::Root {
311 module,
312 source: TextSource(source),
313 })
314}
315
316trait Transform<'s>: Sized {
317 type Target;
318 fn transform(self, ctx: &mut Context<'s>) -> Result<'s, Self::Target>;
319}
320
321impl<'s, T: Transform<'s>> Transform<'s> for Vec<T> {
322 type Target = Vec<T::Target>;
323 fn transform(self, ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
324 self.into_iter().map(|n| n.transform(ctx)).collect()
325 }
326}
327
328impl<'s, T: Transform<'s>> Transform<'s> for Option<T> {
329 type Target = Option<T::Target>;
330 fn transform(self, ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
331 self.map(|n| n.transform(ctx)).transpose()
332 }
333}
334
335impl<'s> Transform<'s> for wat::Module<'s> {
336 type Target = wasm::Module<'s>;
337 fn transform(self, ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
338 ctx.types.reserve(self.types.len());
339 for type_def in self.types.iter() {
340 ctx.types.push(type_def.ty.clone());
341 }
342 Ok(wasm::Module {
343 start: self.start,
344 id: self.id,
345 types: self.types.transform(ctx)?,
346 exports: self.exports.transform(ctx)?,
347 funcs: self.funcs.transform(ctx)?,
348 elems: self.elems.transform(ctx)?,
349 tables: self.tables.transform(ctx)?,
350 data: self.data.transform(ctx)?,
351 memories: self.memories.transform(ctx)?,
352 globals: self.globals.transform(ctx)?,
353 entrypoint: self.entrypoint.transform(ctx)?,
354 })
355 }
356}
357
358impl<'s> Transform<'s> for wat::ValType {
359 type Target = wasm::ValType;
360 fn transform(self, _ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
361 Ok(match self {
362 wat::ValType::I32 => wasm::ValType::I32,
363 wat::ValType::I64 => wasm::ValType::I64,
364 wat::ValType::F32 => wasm::ValType::F32,
365 wat::ValType::F64 => wasm::ValType::F64,
366 })
367 }
368}
369
370impl<'s> Transform<'s> for wat::TypeDef<'s> {
371 type Target = wasm::FuncType;
372 fn transform(self, ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
373 Ok(wasm::FuncType {
374 start: self.start,
375 params: self
376 .ty
377 .params
378 .iter()
379 .map(|p| p.ty.transform(ctx))
380 .collect::<Result<'_, _>>()?,
381 results: self
382 .ty
383 .results
384 .iter()
385 .map(|p| p.ty.transform(ctx))
386 .collect::<Result<'_, _>>()?,
387 })
388 }
389}
390
391impl<'s> Transform<'s> for wat::Name<'s> {
392 type Target = wasm::Name<'s>;
393 fn transform(self, _ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
394 Ok(wasm::Name(self.0))
395 }
396}
397
398impl<'s> Transform<'s> for wat::Export<'s> {
399 type Target = wasm::Export<'s>;
400 fn transform(self, ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
401 let start = self.start;
402 Ok(wasm::Export {
403 start,
404 name: self.name.transform(ctx)?,
405 kind: match self.kind {
406 wat::ExportKind::Func => {
407 let idx = ctx.resolve_func_idx(self.idx, start)?;
408 wasm::ExportKind::Func(idx)
409 }
410 wat::ExportKind::Table => {
411 let idx = ctx.resolve_table_idx(self.idx, start)?;
412 wasm::ExportKind::Table(idx)
413 }
414 wat::ExportKind::Memory => {
415 let idx = ctx.resolve_mem_idx(self.idx, start)?;
416 wasm::ExportKind::Memory(idx)
417 }
418 wat::ExportKind::Global => {
419 let idx = ctx.resolve_global_idx(self.idx, start)?;
420 wasm::ExportKind::Global(idx)
421 }
422 },
423 })
424 }
425}
426
427impl<'s> Transform<'s> for wat::Import<'s> {
428 type Target = wasm::Import<'s>;
429 fn transform(self, ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
430 Ok(wasm::Import {
431 mod_name: self.mod_name.transform(ctx)?,
432 name: self.name.transform(ctx)?,
433 })
434 }
435}
436
437impl<'s> Transform<'s> for wat::Mem {
438 type Target = wasm::Mem;
439 fn transform(self, _ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
440 Ok(wasm::Mem {
441 align: self.align,
442 offset: self.offset,
443 })
444 }
445}
446
447impl<'s> Transform<'s> for wat::Instruction<'s> {
448 type Target = wasm::Instruction;
449 fn transform(self, ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
450 let start = self.start;
451 let kind = match self.kind {
452 wat::InsnKind::Block { label, ty, body, id } => {
453 ctx.label_stack.push(label, id, start)?;
454 let body = body.transform(ctx)?;
455 ctx.label_stack.pop();
456 wasm::InsnKind::Block {
457 ty: ty.transform(ctx)?,
458 body,
459 }
460 }
461 wat::InsnKind::Loop { label, ty, body, id } => {
462 ctx.label_stack.push(label, id, start)?;
463 let body = body.transform(ctx)?;
464 ctx.label_stack.pop();
465 wasm::InsnKind::Loop {
466 ty: ty.transform(ctx)?,
467 body,
468 }
469 }
470 wat::InsnKind::If {
471 label,
472 ty,
473 then_body,
474 else_id,
475 else_body,
476 end_id,
477 } => {
478 ctx.label_stack.push(label, else_id, start)?;
479 let then_body = then_body.transform(ctx)?;
480 ctx.label_stack.pop();
481 ctx.label_stack.push(label, end_id, start)?;
482 let else_body = else_body.transform(ctx)?;
483 ctx.label_stack.pop();
484 wasm::InsnKind::If {
485 ty: ty.transform(ctx)?,
486 then_body,
487 else_body,
488 }
489 }
490 wat::InsnKind::Unreachable => wasm::InsnKind::Unreachable,
491 wat::InsnKind::Nop => wasm::InsnKind::Nop,
492 wat::InsnKind::Br(idx) => wasm::InsnKind::Br(ctx.label_stack.resolve(idx, start)?),
493 wat::InsnKind::BrIf(idx) => wasm::InsnKind::BrIf(ctx.label_stack.resolve(idx, start)?),
494 wat::InsnKind::BrTable { labels, default_label } => wasm::InsnKind::BrTable {
495 labels: labels
496 .into_iter()
497 .map(|idx| ctx.label_stack.resolve(idx, start))
498 .collect::<Result<'_, _>>()?,
499 default_label: ctx.label_stack.resolve(default_label, start)?,
500 },
501 wat::InsnKind::Return => wasm::InsnKind::Return,
502 wat::InsnKind::Call(idx) => wasm::InsnKind::Call(ctx.resolve_func_idx(idx, start)?),
503 wat::InsnKind::CallIndirect(ty) => wasm::InsnKind::CallIndirect(ctx.resolve_type_idx(ty, start)?),
504 wat::InsnKind::Drop => wasm::InsnKind::Drop,
506 wat::InsnKind::Select => wasm::InsnKind::Select,
507 wat::InsnKind::LocalGet(idx) => wasm::InsnKind::LocalGet(ctx.resolve_local_idx(idx, start)?),
509 wat::InsnKind::LocalSet(idx) => wasm::InsnKind::LocalSet(ctx.resolve_local_idx(idx, start)?),
510 wat::InsnKind::LocalTee(idx) => wasm::InsnKind::LocalTee(ctx.resolve_local_idx(idx, start)?),
511 wat::InsnKind::GlobalGet(idx) => wasm::InsnKind::GlobalGet(ctx.resolve_global_idx(idx, start)?),
512 wat::InsnKind::GlobalSet(idx) => wasm::InsnKind::GlobalSet(ctx.resolve_global_idx(idx, start)?),
513 wat::InsnKind::I32Load(mem) => wasm::InsnKind::I32Load(mem.transform(ctx)?),
515 wat::InsnKind::I64Load(mem) => wasm::InsnKind::I64Load(mem.transform(ctx)?),
516 wat::InsnKind::F32Load(mem) => wasm::InsnKind::F32Load(mem.transform(ctx)?),
517 wat::InsnKind::F64Load(mem) => wasm::InsnKind::F64Load(mem.transform(ctx)?),
518 wat::InsnKind::I32Load8S(mem) => wasm::InsnKind::I32Load8S(mem.transform(ctx)?),
519 wat::InsnKind::I32Load8U(mem) => wasm::InsnKind::I32Load8U(mem.transform(ctx)?),
520 wat::InsnKind::I32Load16S(mem) => wasm::InsnKind::I32Load16S(mem.transform(ctx)?),
521 wat::InsnKind::I32Load16U(mem) => wasm::InsnKind::I32Load16U(mem.transform(ctx)?),
522 wat::InsnKind::I64Load8S(mem) => wasm::InsnKind::I64Load8S(mem.transform(ctx)?),
523 wat::InsnKind::I64Load8U(mem) => wasm::InsnKind::I64Load8U(mem.transform(ctx)?),
524 wat::InsnKind::I64Load16S(mem) => wasm::InsnKind::I64Load16S(mem.transform(ctx)?),
525 wat::InsnKind::I64Load16U(mem) => wasm::InsnKind::I64Load16U(mem.transform(ctx)?),
526 wat::InsnKind::I64Load32S(mem) => wasm::InsnKind::I64Load32S(mem.transform(ctx)?),
527 wat::InsnKind::I64Load32U(mem) => wasm::InsnKind::I64Load32U(mem.transform(ctx)?),
528 wat::InsnKind::I32Store(mem) => wasm::InsnKind::I32Store(mem.transform(ctx)?),
529 wat::InsnKind::I64Store(mem) => wasm::InsnKind::I64Store(mem.transform(ctx)?),
530 wat::InsnKind::F32Store(mem) => wasm::InsnKind::F32Store(mem.transform(ctx)?),
531 wat::InsnKind::F64Store(mem) => wasm::InsnKind::F64Store(mem.transform(ctx)?),
532 wat::InsnKind::I32Store8(mem) => wasm::InsnKind::I32Store8(mem.transform(ctx)?),
533 wat::InsnKind::I32Store16(mem) => wasm::InsnKind::I32Store16(mem.transform(ctx)?),
534 wat::InsnKind::I64Store8(mem) => wasm::InsnKind::I64Store8(mem.transform(ctx)?),
535 wat::InsnKind::I64Store16(mem) => wasm::InsnKind::I64Store16(mem.transform(ctx)?),
536 wat::InsnKind::I64Store32(mem) => wasm::InsnKind::I64Store32(mem.transform(ctx)?),
537 wat::InsnKind::MemorySize => wasm::InsnKind::MemorySize,
538 wat::InsnKind::MemoryGrow => wasm::InsnKind::MemoryGrow,
539 wat::InsnKind::I32Const(val) => wasm::InsnKind::I32Const(val),
543 wat::InsnKind::I64Const(val) => wasm::InsnKind::I64Const(val),
544 wat::InsnKind::F32Const(val) => wasm::InsnKind::F32Const(val),
545 wat::InsnKind::F64Const(val) => wasm::InsnKind::F64Const(val),
546 wat::InsnKind::I32Clz => wasm::InsnKind::I32Clz,
548 wat::InsnKind::I32Ctz => wasm::InsnKind::I32Ctz,
549 wat::InsnKind::I32Popcnt => wasm::InsnKind::I32Popcnt,
550 wat::InsnKind::I32Add => wasm::InsnKind::I32Add,
551 wat::InsnKind::I32Sub => wasm::InsnKind::I32Sub,
552 wat::InsnKind::I32Mul => wasm::InsnKind::I32Mul,
553 wat::InsnKind::I32DivS => wasm::InsnKind::I32DivS,
554 wat::InsnKind::I32DivU => wasm::InsnKind::I32DivU,
555 wat::InsnKind::I32RemS => wasm::InsnKind::I32RemS,
556 wat::InsnKind::I32RemU => wasm::InsnKind::I32RemU,
557 wat::InsnKind::I32And => wasm::InsnKind::I32And,
558 wat::InsnKind::I32Or => wasm::InsnKind::I32Or,
559 wat::InsnKind::I32Xor => wasm::InsnKind::I32Xor,
560 wat::InsnKind::I32Shl => wasm::InsnKind::I32Shl,
561 wat::InsnKind::I32ShrS => wasm::InsnKind::I32ShrS,
562 wat::InsnKind::I32ShrU => wasm::InsnKind::I32ShrU,
563 wat::InsnKind::I32Rotl => wasm::InsnKind::I32Rotl,
564 wat::InsnKind::I32Rotr => wasm::InsnKind::I32Rotr,
565 wat::InsnKind::I64Clz => wasm::InsnKind::I64Clz,
567 wat::InsnKind::I64Ctz => wasm::InsnKind::I64Ctz,
568 wat::InsnKind::I64Popcnt => wasm::InsnKind::I64Popcnt,
569 wat::InsnKind::I64Add => wasm::InsnKind::I64Add,
570 wat::InsnKind::I64Sub => wasm::InsnKind::I64Sub,
571 wat::InsnKind::I64Mul => wasm::InsnKind::I64Mul,
572 wat::InsnKind::I64DivS => wasm::InsnKind::I64DivS,
573 wat::InsnKind::I64DivU => wasm::InsnKind::I64DivU,
574 wat::InsnKind::I64RemS => wasm::InsnKind::I64RemS,
575 wat::InsnKind::I64RemU => wasm::InsnKind::I64RemU,
576 wat::InsnKind::I64And => wasm::InsnKind::I64And,
577 wat::InsnKind::I64Or => wasm::InsnKind::I64Or,
578 wat::InsnKind::I64Xor => wasm::InsnKind::I64Xor,
579 wat::InsnKind::I64Shl => wasm::InsnKind::I64Shl,
580 wat::InsnKind::I64ShrS => wasm::InsnKind::I64ShrS,
581 wat::InsnKind::I64ShrU => wasm::InsnKind::I64ShrU,
582 wat::InsnKind::I64Rotl => wasm::InsnKind::I64Rotl,
583 wat::InsnKind::I64Rotr => wasm::InsnKind::I64Rotr,
584 wat::InsnKind::F32Abs => wasm::InsnKind::F32Abs,
586 wat::InsnKind::F32Neg => wasm::InsnKind::F32Neg,
587 wat::InsnKind::F32Ceil => wasm::InsnKind::F32Ceil,
588 wat::InsnKind::F32Floor => wasm::InsnKind::F32Floor,
589 wat::InsnKind::F32Trunc => wasm::InsnKind::F32Trunc,
590 wat::InsnKind::F32Nearest => wasm::InsnKind::F32Nearest,
591 wat::InsnKind::F32Sqrt => wasm::InsnKind::F32Sqrt,
592 wat::InsnKind::F32Add => wasm::InsnKind::F32Add,
593 wat::InsnKind::F32Sub => wasm::InsnKind::F32Sub,
594 wat::InsnKind::F32Mul => wasm::InsnKind::F32Mul,
595 wat::InsnKind::F32Div => wasm::InsnKind::F32Div,
596 wat::InsnKind::F32Min => wasm::InsnKind::F32Min,
597 wat::InsnKind::F32Max => wasm::InsnKind::F32Max,
598 wat::InsnKind::F32Copysign => wasm::InsnKind::F32Copysign,
599 wat::InsnKind::F64Abs => wasm::InsnKind::F64Abs,
601 wat::InsnKind::F64Neg => wasm::InsnKind::F64Neg,
602 wat::InsnKind::F64Ceil => wasm::InsnKind::F64Ceil,
603 wat::InsnKind::F64Floor => wasm::InsnKind::F64Floor,
604 wat::InsnKind::F64Trunc => wasm::InsnKind::F64Trunc,
605 wat::InsnKind::F64Nearest => wasm::InsnKind::F64Nearest,
606 wat::InsnKind::F64Sqrt => wasm::InsnKind::F64Sqrt,
607 wat::InsnKind::F64Add => wasm::InsnKind::F64Add,
608 wat::InsnKind::F64Sub => wasm::InsnKind::F64Sub,
609 wat::InsnKind::F64Mul => wasm::InsnKind::F64Mul,
610 wat::InsnKind::F64Div => wasm::InsnKind::F64Div,
611 wat::InsnKind::F64Min => wasm::InsnKind::F64Min,
612 wat::InsnKind::F64Max => wasm::InsnKind::F64Max,
613 wat::InsnKind::F64Copysign => wasm::InsnKind::F64Copysign,
614 wat::InsnKind::I32Eqz => wasm::InsnKind::I32Eqz,
616 wat::InsnKind::I32Eq => wasm::InsnKind::I32Eq,
617 wat::InsnKind::I32Ne => wasm::InsnKind::I32Ne,
618 wat::InsnKind::I32LtS => wasm::InsnKind::I32LtS,
619 wat::InsnKind::I32LtU => wasm::InsnKind::I32LtU,
620 wat::InsnKind::I32GtS => wasm::InsnKind::I32GtS,
621 wat::InsnKind::I32GtU => wasm::InsnKind::I32GtU,
622 wat::InsnKind::I32LeS => wasm::InsnKind::I32LeS,
623 wat::InsnKind::I32LeU => wasm::InsnKind::I32LeU,
624 wat::InsnKind::I32GeS => wasm::InsnKind::I32GeS,
625 wat::InsnKind::I32GeU => wasm::InsnKind::I32GeU,
626 wat::InsnKind::I64Eqz => wasm::InsnKind::I64Eqz,
628 wat::InsnKind::I64Eq => wasm::InsnKind::I64Eq,
629 wat::InsnKind::I64Ne => wasm::InsnKind::I64Ne,
630 wat::InsnKind::I64LtS => wasm::InsnKind::I64LtS,
631 wat::InsnKind::I64LtU => wasm::InsnKind::I64LtU,
632 wat::InsnKind::I64GtS => wasm::InsnKind::I64GtS,
633 wat::InsnKind::I64GtU => wasm::InsnKind::I64GtU,
634 wat::InsnKind::I64LeS => wasm::InsnKind::I64LeS,
635 wat::InsnKind::I64LeU => wasm::InsnKind::I64LeU,
636 wat::InsnKind::I64GeS => wasm::InsnKind::I64GeS,
637 wat::InsnKind::I64GeU => wasm::InsnKind::I64GeU,
638 wat::InsnKind::F32Eq => wasm::InsnKind::F32Eq,
640 wat::InsnKind::F32Ne => wasm::InsnKind::F32Ne,
641 wat::InsnKind::F32Lt => wasm::InsnKind::F32Lt,
642 wat::InsnKind::F32Gt => wasm::InsnKind::F32Gt,
643 wat::InsnKind::F32Le => wasm::InsnKind::F32Le,
644 wat::InsnKind::F32Ge => wasm::InsnKind::F32Ge,
645 wat::InsnKind::F64Eq => wasm::InsnKind::F64Eq,
647 wat::InsnKind::F64Ne => wasm::InsnKind::F64Ne,
648 wat::InsnKind::F64Lt => wasm::InsnKind::F64Lt,
649 wat::InsnKind::F64Gt => wasm::InsnKind::F64Gt,
650 wat::InsnKind::F64Le => wasm::InsnKind::F64Le,
651 wat::InsnKind::F64Ge => wasm::InsnKind::F64Ge,
652 wat::InsnKind::I32WrapI64 => wasm::InsnKind::I32WrapI64,
654 wat::InsnKind::I32TruncF32S => wasm::InsnKind::I32TruncF32S,
655 wat::InsnKind::I32TruncF32U => wasm::InsnKind::I32TruncF32U,
656 wat::InsnKind::I32TruncF64S => wasm::InsnKind::I32TruncF64S,
657 wat::InsnKind::I32TruncF64U => wasm::InsnKind::I32TruncF64U,
658 wat::InsnKind::I64ExtendI32S => wasm::InsnKind::I64ExtendI32S,
659 wat::InsnKind::I64ExtendI32U => wasm::InsnKind::I64ExtendI32U,
660 wat::InsnKind::I64TruncF32S => wasm::InsnKind::I64TruncF32S,
661 wat::InsnKind::I64TruncF32U => wasm::InsnKind::I64TruncF32U,
662 wat::InsnKind::I64TruncF64S => wasm::InsnKind::I64TruncF64S,
663 wat::InsnKind::I64TruncF64U => wasm::InsnKind::I64TruncF64U,
664 wat::InsnKind::F32ConvertI32S => wasm::InsnKind::F32ConvertI32S,
665 wat::InsnKind::F32ConvertI32U => wasm::InsnKind::F32ConvertI32U,
666 wat::InsnKind::F32ConvertI64S => wasm::InsnKind::F32ConvertI64S,
667 wat::InsnKind::F32ConvertI64U => wasm::InsnKind::F32ConvertI64U,
668 wat::InsnKind::F32DemoteF64 => wasm::InsnKind::F32DemoteF64,
669 wat::InsnKind::F64ConvertI32S => wasm::InsnKind::F64ConvertI32S,
670 wat::InsnKind::F64ConvertI32U => wasm::InsnKind::F64ConvertI32U,
671 wat::InsnKind::F64ConvertI64S => wasm::InsnKind::F64ConvertI64S,
672 wat::InsnKind::F64ConvertI64U => wasm::InsnKind::F64ConvertI64U,
673 wat::InsnKind::F64PromoteF32 => wasm::InsnKind::F64PromoteF32,
674 wat::InsnKind::I32ReinterpretF32 => wasm::InsnKind::I32ReinterpretF32,
675 wat::InsnKind::I64ReinterpretF64 => wasm::InsnKind::I64ReinterpretF64,
676 wat::InsnKind::F32ReinterpretI32 => wasm::InsnKind::F32ReinterpretI32,
677 wat::InsnKind::F64ReinterpretI64 => wasm::InsnKind::F64ReinterpretI64,
678 wat::InsnKind::I32Extend8S => wasm::InsnKind::I32Extend8S,
680 wat::InsnKind::I32Extend16S => wasm::InsnKind::I32Extend16S,
681 wat::InsnKind::I64Extend8S => wasm::InsnKind::I64Extend8S,
682 wat::InsnKind::I64Extend16S => wasm::InsnKind::I64Extend16S,
683 wat::InsnKind::I64Extend32S => wasm::InsnKind::I64Extend32S,
684 };
685 Ok(wasm::Instruction { start, kind })
686 }
687}
688
689impl<'s> Transform<'s> for wat::Func<'s> {
690 type Target = wasm::Func<'s>;
691 fn transform(self, ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
692 Ok(wasm::Func {
693 start: self.start,
694 kind: match self.kind {
695 wat::FuncKind::Import(import) => wasm::FuncKind::Import(import.transform(ctx)?),
696 wat::FuncKind::Body { locals, body } => {
697 ctx.start_func_scope();
698 for param in self.ty.params.iter() {
699 ctx.new_local_idx(param.id, self.start)?;
700 }
701 for local in locals.iter() {
702 ctx.new_local_idx(local.id, self.start)?;
703 }
704
705 wasm::FuncKind::Body {
706 locals: locals.iter().map(|l| l.ty.transform(ctx)).collect::<Result<'_, _>>()?,
707 expr: body.transform(ctx)?,
708 }
709 }
710 },
711 idx: ctx.resolve_type_idx(self.ty, self.start)?,
712 })
713 }
714}
715
716impl<'s> Transform<'s> for wat::Elem<'s> {
717 type Target = wasm::ElemSegment;
718 fn transform(self, ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
719 let start = self.start;
720 Ok(wasm::ElemSegment {
721 start,
722 idx: ctx.resolve_table_idx(self.idx, start)?,
723 offset: self.offset.transform(ctx)?,
724 init: self
725 .init
726 .into_iter()
727 .map(|idx| ctx.resolve_func_idx(idx, start))
728 .collect::<Result<'_, _>>()?,
729 })
730 }
731}
732
733impl<'s> Transform<'s> for wat::Limits {
734 type Target = wasm::Limits;
735 fn transform(self, _ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
736 Ok(match self {
737 wat::Limits::Range { min, max } => wasm::Limits::Range(min, max),
738 wat::Limits::From { min } => wasm::Limits::From(min),
739 })
740 }
741}
742
743impl<'s> Transform<'s> for wat::Table<'s> {
744 type Target = wasm::Table<'s>;
745 fn transform(self, ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
746 Ok(wasm::Table {
747 start: self.start,
748 ty: wasm::TableType {
749 limit: self.ty.limit.transform(ctx)?,
750 },
751 import: self.import.transform(ctx)?,
752 })
753 }
754}
755
756impl<'s> Transform<'s> for wat::Data<'s> {
757 type Target = wasm::DataSegment<'s>;
758 fn transform(self, ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
759 Ok(wasm::DataSegment {
760 start: self.start,
761 idx: ctx.resolve_mem_idx(self.idx, self.start)?,
762 offset: self.offset.transform(ctx)?,
763 data: self.data,
764 })
765 }
766}
767
768impl<'s> Transform<'s> for wat::Memory<'s> {
769 type Target = wasm::Memory<'s>;
770 fn transform(self, ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
771 Ok(wasm::Memory {
772 start: self.start,
773 ty: wasm::MemType {
774 limit: self.ty.limit.transform(ctx)?,
775 },
776 import: self.import.transform(ctx)?,
777 })
778 }
779}
780
781impl<'s> Transform<'s> for wat::Global<'s> {
782 type Target = wasm::Global<'s>;
783 fn transform(self, ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
784 Ok(wasm::Global {
785 start: self.start,
786 mutable: self.ty.mutable,
787 ty: self.ty.ty.transform(ctx)?,
788 kind: match self.kind {
789 wat::GlobalKind::Import(import) => wasm::GlobalKind::Import(import.transform(ctx)?),
790 wat::GlobalKind::Init(init) => wasm::GlobalKind::Init(init.transform(ctx)?),
791 },
792 })
793 }
794}
795
796impl<'s> Transform<'s> for wat::Start<'s> {
797 type Target = wasm::StartFunction;
798 fn transform(self, ctx: &mut Context<'s>) -> Result<'s, Self::Target> {
799 Ok(wasm::StartFunction {
800 start: self.start,
801 idx: ctx.resolve_func_idx(self.idx, self.start)?,
802 })
803 }
804}