web_assembler/
builder.rs

1use std::ops::{Range, RangeFrom};
2
3use module::*;
4use types::*;
5use ops;
6use ops::Op;
7pub struct ModuleBuilder(Module);
8
9macro_rules! gen_add {
10    ($name: tt ($param: tt, $ty: ty) -> $ret: tt, $field: tt) => {
11        pub fn $name(&mut self, ty: $ty) -> $ret {
12
13            match &mut (self.0).$field {
14                &mut Some(ref mut v) => {
15                    v.push(ty);
16                    $ret::new((v.len() - 1) as u32)
17                },
18                none => {
19                    *none = Some(vec![ty]);
20                    $ret::new(0)
21                },
22            }
23        }
24    };
25
26    (prv, $name: tt ($param: tt, $ty: ty) -> $ret: tt, $field: tt) => {
27        fn $name(&mut self, ty: $ty) -> $ret {
28
29            match &mut (self.0).$field {
30                &mut Some(ref mut v) => {
31                    v.push(ty);
32                    $ret::new((v.len() - 1) as u32)
33                },
34                none => {
35                    *none = Some(vec![ty]);
36                    $ret::new(0)
37                },
38            }
39        }
40    };
41}
42
43impl ModuleBuilder {
44    pub fn new() -> Self {
45        ModuleBuilder(Module {
46                          unknown: None,
47                          types: None,
48                          imports: None,
49                          functions: None,
50                          tables: None,
51                          memories: None,
52                          globals: None,
53                          exports: None,
54                          start: None,
55                          elements: None,
56                          codes: None,
57                          data: None,
58                      })
59    }
60
61    pub fn function_index_of(&self, i: ImportIndex) -> Result<FunctionSpaceIndex, ImportIndex> {
62        self.0.function_index_of(i)
63    }
64
65    fn nimports(&self) -> u32 {
66        self.0
67            .imports
68            .iter()
69            .flat_map(|i| i.iter())
70            .filter(|i|  i.kind.is_function())
71            .count() as u32
72    }
73
74    fn resolve_functions(&mut self) {
75        let nimports = self.nimports();
76        // resolve codes
77        for f in self.0.codes.iter_mut().flat_map(|f| f.iter_mut()) {
78            f.resolve_functions(nimports)
79        }
80        // resolve tables
81        for e in self.0.elements.iter_mut().flat_map(|e| e.iter_mut()) {
82            for index in e.elems.iter_mut() {
83                use InnerFunctionSpaceIndex::*;
84                match index.0 {
85                    Function(ref mut f) => {
86                        f.0 += nimports;
87                    }
88                    _ => (),
89                }
90            }
91        }
92    }
93
94    pub fn build(mut self) -> Module {
95        self.resolve_functions();
96        let nimports = self.nimports();
97        self.0.start.as_mut().map(|i| i.0 += nimports);
98        self.0
99    }
100
101
102    gen_add!(add_type(ty, FuncType) -> TypeIndex,
103             types);
104    gen_add!(add_import(import, ImportEntry) -> ImportIndex,
105             imports);
106    gen_add!(prv, add_function(func, Function) -> FunctionIndex,
107             functions);
108    gen_add!(add_table(table, TableType) -> TableIndex,
109             tables);
110    gen_add!(add_memory(memory, MemoryType) -> MemoryIndex,
111             memories);
112    gen_add!(add_global(global, GlobalVariable) -> GlobalIndex,
113             globals);
114    gen_add!(add_export(export, ExportEntry) -> ExportIndex,
115             exports);
116    pub fn start(&mut self, index: FunctionIndex) {
117        self.0.start = Some(index);
118    }
119    gen_add!(add_element(element, ElemSegment) -> ElementIndex,
120                 elements);
121    gen_add!(prv, add_code(code, FunctionBody) -> CodeIndex,
122             codes);
123    gen_add!(add_data(data, DataSegment) -> DataIndex,
124             data);
125
126    pub fn new_function(&mut self, (t, body): (FuncType, FunctionBody)) -> FunctionIndex {
127        let tidx = self.add_type(t);
128        let fidx = self.add_function(Function(tidx));
129        let cidx = self.add_code(body);
130        assert_eq!(*cidx, *fidx);
131        fidx
132    }
133
134    pub fn new_data(&mut self, idx: MemoryIndex, offset: Code, data: Vec<u8>) -> DataIndex {
135        let seg = DataSegment {
136            index: idx,
137            offset: InitExpr(offset),
138            data: data,
139        };
140        self.add_data(seg)
141    }
142
143    pub fn new_global(&mut self, ty: GlobalType, init: Code) -> GlobalIndex {
144        self.add_global(GlobalVariable {
145                            ty: ty,
146                            init: InitExpr(init),
147                        })
148    }
149}
150
151pub trait NewTable<T> {
152    fn new_table(&mut self, element: ElemType, range: T) -> TableIndex;
153}
154
155impl NewTable<Range<u32>> for ModuleBuilder {
156    fn new_table(&mut self, element: ElemType, range: Range<u32>) -> TableIndex {
157        let table = TableType {
158            element: element,
159            limits: ResizableLimits::new(range.start).max(range.end),
160        };
161        self.add_table(table)
162    }
163}
164
165impl NewTable<RangeFrom<u32>> for ModuleBuilder {
166    fn new_table(&mut self, element: ElemType, range: RangeFrom<u32>) -> TableIndex {
167        let table = TableType {
168            element: element,
169            limits: ResizableLimits::new(range.start),
170        };
171        self.add_table(table)
172    }
173}
174
175pub trait NewMemory<T> {
176    fn new_memory(&mut self, range: T) -> MemoryIndex;
177}
178
179impl NewMemory<Range<u32>> for ModuleBuilder {
180    fn new_memory(&mut self, range: Range<u32>) -> MemoryIndex {
181        let memory = MemoryType { limits: ResizableLimits::new(range.start).max(range.end) };
182        self.add_memory(memory)
183    }
184}
185
186impl NewMemory<RangeFrom<u32>> for ModuleBuilder {
187    fn new_memory(&mut self, range: RangeFrom<u32>) -> MemoryIndex {
188        let memory = MemoryType { limits: ResizableLimits::new(range.start) };
189        self.add_memory(memory)
190    }
191}
192
193pub trait Export<T> {
194    fn export<S: Into<String>>(&mut self, name: S, index: T) -> ExportIndex;
195}
196
197
198macro_rules! gen_export {
199    ($name: ty, $variant: tt) => {
200        impl Export<$name> for ModuleBuilder {
201        fn export<S: Into<String>>(&mut self, name: S, index: $name) -> ExportIndex {
202            let entry = ExportEntry {
203                field: name.into(),
204                kind: ExportKind::$variant(index),
205            };
206            self.add_export(entry)
207        }
208        }
209    }
210}
211
212gen_export!(FunctionIndex, Function);
213gen_export!(TableIndex, Table);
214gen_export!(MemoryIndex, Memory);
215gen_export!(GlobalIndex, Global);
216
217
218pub trait Import<Ty> {
219    fn import<S, T>(&mut self, module: S, name: T, index: Ty) -> ImportIndex
220        where S: Into<String>,
221              T: Into<String>;
222}
223
224macro_rules! gen_import {
225    ($name: ty, $variant: tt) => {
226        impl Import<$name> for ModuleBuilder {
227            fn import<S, T>(&mut self, module: S, name: T, index: $name) -> ImportIndex
228                where S: Into<String>,
229                      T: Into<String>
230            {
231            let entry = ImportEntry {
232                module: module.into(),
233                field: name.into(),
234                kind: ImportKind::$variant(index),
235            };
236            self.add_import(entry)
237        }
238        }
239    }
240}
241
242gen_import!(TypeIndex, Function);
243gen_import!(TableType, Table);
244gen_import!(MemoryType, Memory);
245gen_import!(GlobalType, Global);
246
247
248pub trait NewFunction<T> {
249    fn new_function(&mut self, t: T, body: FunctionBody) -> FunctionIndex;
250}
251
252impl NewFunction<TypeIndex> for ModuleBuilder {
253    fn new_function(&mut self, t: TypeIndex, body: FunctionBody) -> FunctionIndex {
254        let fidx = self.add_function(Function(t));
255        let cidx = self.add_code(body);
256        assert_eq!(*cidx, *fidx);
257        fidx
258    }
259}
260
261impl NewFunction<FuncType> for ModuleBuilder {
262    fn new_function(&mut self, t: FuncType, body: FunctionBody) -> FunctionIndex {
263        self.new_function((t, body))
264    }
265}
266
267
268
269pub struct CodeBuilder {
270    code: Vec<Op>,
271}
272
273macro_rules! gen_builder {
274    ($variant: path, $fname: ident) => {
275        pub fn $fname(mut self) -> Self {
276            self.code.push($variant);
277            self
278        }
279    };
280    ($variant: tt {$($arg: ident : $argty: ty, )* }, $fname: ident) => {
281        pub fn $fname(mut self, $($arg: $argty, )*) -> Self {
282            self.code.push($variant {
283                $($arg : $arg, )*
284            });
285            self
286        }
287    };
288
289    ($variant: tt { $arg: ident : $argty: ty $(, $args: ident : $argtys: ty)* }, $fname: ident) => {
290        gen_builder!($variant {$arg: $argty $(, $args : $argtys)*, }, $fname);
291    };
292
293    ($variant: tt [$($arg: ident : $argty: ty, )*], $fname: ident) => {
294        pub fn $fname(mut self, $($arg: $argty, )*) -> Self {
295            self.code.push($variant($($arg, )*));
296            self
297        }
298    };
299
300    ($variant: tt [ $arg: ident : $argty: ty  $(, $args: ident : $argtys: ty)*], $fname: ident) => {
301        gen_builder!($variant [$arg: $argty $(, $args : $argtys)*, ], $fname);
302    };
303}
304
305macro_rules! gen_memory_builder {
306    ($variant: tt, $fname: ident, $align: expr) => {
307        pub fn $fname(mut self, offset: u32) -> Self {
308            let imm = ops::MemoryImmediate{
309                flags: $align - 3,
310                offset: offset
311            };
312            self.code.push($variant{imm: imm});
313            self
314        }
315    };
316
317}
318use Op::*;
319
320impl CodeBuilder {
321    pub fn new() -> Self {
322        CodeBuilder { code: Vec::new() }
323    }
324
325    pub fn build(self) -> Code {
326        Code(self.code)
327    }
328
329    gen_builder!(Unreachable, unreachable);
330    gen_builder!(Nop, nop);
331    gen_builder!(Block { sig: BlockType }, block);
332    gen_builder!(Loop { sig: BlockType }, loop_);
333    gen_builder!(If { sig: BlockType }, if_);
334    gen_builder!(Else, else_);
335    gen_builder!(End, end);
336    gen_builder!(Br { depth: u32 }, br);
337    gen_builder!(BrIf { depth: u32 }, br_if);
338    pub fn br_table(mut self, table: Vec<u32>, default: u32) -> Self {
339        self.code
340            .push(BrTable(ops::BrTarget {
341                              table: table,
342                              default_target: default,
343                          }));
344        self
345    }
346    gen_builder!(Return, return_);
347
348    gen_builder!(Call { index: FunctionSpaceIndex }, call);
349    gen_builder!(CallIndirect {
350                     index: TypeIndex,
351                     reserved: bool,
352                 },
353                 call_indirect);
354
355    gen_builder!(Drop, drop);
356    gen_builder!(Select, select);
357
358    gen_builder!(GetLocal[idx: LocalIndex], get_local);
359    gen_builder!(SetLocal[idx: LocalIndex], set_local);
360    gen_builder!(TeeLocal[idx: LocalIndex], tee_local);
361    gen_builder!(GetGlobal[idx: GlobalIndex], get_global);
362    gen_builder!(SetGlobal[idx: GlobalIndex], set_global);
363
364    // TODO: generate with-flag API too.
365    gen_memory_builder!(I32Load, i32_load, 5);
366    gen_memory_builder!(I64Load, i64_load, 6);
367    gen_memory_builder!(F32Load, f32_load, 5);
368    gen_memory_builder!(F64Load, f64_load, 6);
369    gen_memory_builder!(I32Load8S, i32_load8_s, 3);
370    gen_memory_builder!(I32Load8U, i32_load8_u, 3);
371    gen_memory_builder!(I32Load16S, i32_load16_s, 4);
372    gen_memory_builder!(I32Load16U, i32_load16_u, 4);
373    gen_memory_builder!(I64Load8S, i64_load8_s, 3);
374    gen_memory_builder!(I64Load8U, i64_load8_u, 3);
375    gen_memory_builder!(I64Load16S, i64_load16_s, 4);
376    gen_memory_builder!(I64Load16U, i64_load16_u, 4);
377    gen_memory_builder!(I64load32S, i64_load32_s, 5);
378    gen_memory_builder!(I64load32U, i64_load32_u, 5);
379    gen_memory_builder!(I32Store, i32_store, 5);
380    gen_memory_builder!(I64Store, i64_store, 6);
381    gen_memory_builder!(F32Store, f32_store, 5);
382    gen_memory_builder!(F64Store, f64_store, 6);
383    gen_memory_builder!(I32Store8, i32_store8, 3);
384    gen_memory_builder!(I32Store16, i32_store16, 4);
385    gen_memory_builder!(I64Store8, i64_store8, 3);
386    gen_memory_builder!(I64Store16, i64_store16, 4);
387    gen_memory_builder!(I64Store32, i64_store32, 5);
388    gen_builder!(CurrentMemory { reserved: bool }, current_memory);
389    gen_builder!(GrowMemory { reserved: bool }, grow_memory);
390
391
392    pub fn constant<C>(mut self, c: C) -> Self
393        where Op: From<C>
394    {
395        self.code.push(Op::from(c));
396        self
397    }
398
399    gen_builder!(I32Eqz, i32_eqz);
400    gen_builder!(I32Eq, i32_eq);
401    gen_builder!(I32NE, i32_ne);
402    gen_builder!(I32LtS, i32_lt_s);
403    gen_builder!(I32LtU, i32_lt_u);
404    gen_builder!(I32GtS, i32_gt_s);
405    gen_builder!(I32GtU, i32_gt_u);
406    gen_builder!(I32LeS, i32_le_s);
407    gen_builder!(I32LeU, i32_le_u);
408    gen_builder!(I32GeS, i32_ge_s);
409    gen_builder!(I32GeU, i32_ge_u);
410    gen_builder!(I64Eqz, i64_eqz);
411    gen_builder!(I64Eq, i64_eq);
412    gen_builder!(I64Ne, i64_ne);
413    gen_builder!(I64LtS, i64_lt_s);
414    gen_builder!(I64LtU, i64_lt_u);
415    gen_builder!(I64GtS, i64_gt_s);
416    gen_builder!(I64GtU, i64_gt_u);
417    gen_builder!(I64LeS, i64_le_s);
418    gen_builder!(I64LeU, i64_le_u);
419    gen_builder!(I64GeS, i64_ge_s);
420    gen_builder!(I64GeU, i64_ge_u);
421    gen_builder!(F32Eq, f32_eq);
422    gen_builder!(F32Ne, f32_ne);
423    gen_builder!(F32Lt, f32_lt);
424    gen_builder!(F32Gt, f32_gt);
425    gen_builder!(F32Le, f32_le);
426    gen_builder!(F32Ge, f32_ge);
427    gen_builder!(F64Eq, f64_eq);
428    gen_builder!(F64Ne, f64_ne);
429    gen_builder!(F64Lt, f64_lt);
430    gen_builder!(F64Gt, f64_gt);
431    gen_builder!(F64Le, f64_le);
432    gen_builder!(F64Ge, f64_ge);
433
434    gen_builder!(I32Clz, i32_clz);
435    gen_builder!(I32Ctz, i32_ctz);
436    gen_builder!(I32Popcnt, i32_popcnt);
437    gen_builder!(I32Add, i32_add);
438    gen_builder!(I32Sub, i32_sub);
439    gen_builder!(I32Mul, i32_mul);
440    gen_builder!(I32DivS, i32_div_s);
441    gen_builder!(I32DivU, i32_div_u);
442    gen_builder!(I32RemS, i32_rem_s);
443    gen_builder!(I32RemU, i32_rem_u);
444    gen_builder!(I32And, i32_and);
445    gen_builder!(I32Or, i32_or);
446    gen_builder!(I32Xor, i32_xor);
447    gen_builder!(I32Shl, i32_shl);
448    gen_builder!(I32ShrS, i32_shr_s);
449    gen_builder!(I32ShrU, i32_shr_u);
450    gen_builder!(I32Rotl, i32_rotl);
451    gen_builder!(I32Rotr, i32_rotr);
452    gen_builder!(I64Clz, i64_clz);
453    gen_builder!(I64Ctz, i64_ctz);
454    gen_builder!(I64Popcnt, i64_popcnt);
455    gen_builder!(I64Add, i64_add);
456    gen_builder!(I64Sub, i64_sub);
457    gen_builder!(I64Mul, i64_mul);
458    gen_builder!(I64DivS, i64_div_s);
459    gen_builder!(I64DivU, i64_div_u);
460    gen_builder!(I64RemS, i64_rem_s);
461    gen_builder!(I64RemU, i64_rem_u);
462    gen_builder!(I64And, i64_and);
463    gen_builder!(I64Or, i64_or);
464    gen_builder!(I64Xor, i64_xor);
465    gen_builder!(I64Shl, i64_shl);
466    gen_builder!(I64ShrS, i64_shr_s);
467    gen_builder!(I64ShrU, i64_shr_u);
468    gen_builder!(I64Rotl, i64_rotl);
469    gen_builder!(I64Rotr, i64_rotr);
470    gen_builder!(F32Abs, f32_abs);
471    gen_builder!(F32Neg, f32_neg);
472    gen_builder!(F32Ceil, f32_ceil);
473    gen_builder!(F32Floor, f32_floor);
474    gen_builder!(F32Trunc, f32_trunc);
475    gen_builder!(F32Nearest, f32_nearest);
476    gen_builder!(F32Sqrt, f32_sqrt);
477    gen_builder!(F32Add, f32_add);
478    gen_builder!(F32Sub, f32_sub);
479    gen_builder!(F32Mul, f32_mul);
480    gen_builder!(F32Div, f32_div);
481    gen_builder!(F32Min, f32_min);
482    gen_builder!(F32Max, f32_max);
483    gen_builder!(F32Copysign, f32_copysign);
484    gen_builder!(F64Abs, f64_abs);
485    gen_builder!(F64Neg, f64_neg);
486    gen_builder!(F64Ceil, f64_ceil);
487    gen_builder!(F64Floor, f64_floor);
488    gen_builder!(F64Trunc, f64_trunc);
489    gen_builder!(F64Nearest, f64_nearest);
490    gen_builder!(F64Sqrt, f64_sqrt);
491    gen_builder!(F64Add, f64_add);
492    gen_builder!(F64Sub, f64_sub);
493    gen_builder!(F64Mul, f64_mul);
494    gen_builder!(F64Div, f64_div);
495    gen_builder!(F64Min, f64_min);
496    gen_builder!(F64Max, f64_max);
497    gen_builder!(F64Copysign, f64_copysign);
498
499    gen_builder!(I32wrapI64, i32_wrap_i64);
500    gen_builder!(I32TruncSF32, i32_trunc_s_f32);
501    gen_builder!(I32TruncUF32, i32_trunc_u_f32);
502    gen_builder!(I32TruncSF64, i32_trunc_s_f64);
503    gen_builder!(I32TruncUF64, i32_trunc_u_f64);
504    gen_builder!(I64ExtendSI32, i64_extend_s_i32);
505    gen_builder!(I64ExtendUI32, i64_extend_u_i32);
506    gen_builder!(I64TruncSF32, i64_trunc_s_f32);
507    gen_builder!(I64TruncUF32, i64_trunc_u_f32);
508    gen_builder!(I64TruncSF64, i64_trunc_s_f64);
509    gen_builder!(I64TruncUF64, i64_trunc_u_f64);
510    gen_builder!(F32ConvertSI32, f32_convert_s_i32);
511    gen_builder!(F32ConvertUI32, f32_convert_u_i32);
512    gen_builder!(F32ConvertSI64, f32_convert_s_i64);
513    gen_builder!(F32ConvertUI64, f32_convert_u_i64);
514    gen_builder!(F32DemoteF64, f32_demote_f64);
515    gen_builder!(F64ConvertSI32, f64_convert_s_i32);
516    gen_builder!(F64ConvertUI32, f64_convert_u_i32);
517    gen_builder!(F64ConvertSI64, f64_convert_s_i64);
518    gen_builder!(F64ConvertUI64, f64_convert_u_i64);
519    gen_builder!(F64PromoteF32, f64_promote_f32);
520
521    gen_builder!(I32ReinterpretF32, i32_reinterpret_f32);
522    gen_builder!(I64ReinterpretF64, i64_reinterpret_f64);
523    gen_builder!(F32ReinterpretI32, f32_reinterpret_i32);
524    gen_builder!(F64ReinterpretI64, f64_reinterpret_i64);
525}
526
527pub struct FunctionBuilder {
528    ty: FuncType,
529    args: Vec<LocalIndex>,
530    locals: Vec<ValueType>,
531    cb: CodeBuilder,
532}
533
534
535impl FunctionBuilder {
536    pub fn new(ty: FuncType) -> Self {
537        let args = (0..ty.params.len())
538            .map(|i| LocalIndex::new(i as u32))
539            .collect();
540        let fb = FunctionBuilder {
541            ty: ty,
542            args: args,
543            locals: Vec::new(),
544            cb: CodeBuilder::new(),
545        };
546        fb
547    }
548
549    pub fn build(self) -> (FuncType, FunctionBody) {
550        // TODO: compact local entry
551        let locals = self.locals
552            .into_iter()
553            .map(|l| LocalEntry { count: 1, ty: l })
554            .collect();
555        let body = FunctionBody {
556            locals: locals,
557            code: self.cb.build(),
558        };
559        (self.ty, body)
560    }
561
562    pub fn new_local(&mut self, ty: ValueType) -> LocalIndex {
563        self.locals.push(ty);
564        LocalIndex::new((self.ty.params.len() + self.locals.len() - 1) as u32)
565    }
566
567    pub fn new_locals(&mut self, tys: Vec<ValueType>) -> Vec<LocalIndex> {
568        tys.into_iter()
569            .map(|ty| {
570                     self.locals.push(ty);
571                     LocalIndex::new((self.ty.params.len() + self.locals.len() - 1) as u32)
572                 })
573            .collect()
574    }
575
576    pub fn code<F: FnOnce(CodeBuilder, &[LocalIndex]) -> CodeBuilder>(mut self, f: F) -> Self {
577        self.cb = f(self.cb, &self.args);
578        self
579    }
580}
581
582#[macro_export]
583macro_rules! ty {
584    (i32) => (ValueType::I32);
585    (i64) => (ValueType::I64);
586    (f32) => (ValueType::F32);
587    (f64) => (ValueType::F64);
588}
589
590
591#[macro_export]
592macro_rules! ty_vec {
593    ($($t: tt, )*) => {
594        vec!($(ty!($t), )*)
595    };
596
597    ($t: tt $(, $ts: tt)*) => {
598        vec!(ty!($t) $(, ty!($ts))*)
599    };
600}
601
602#[macro_export]
603macro_rules! funtype {
604    (($($params: tt)*) -> $ret: tt) => {
605        FuncType {
606            params: ty_vec!($($params)*),
607            ret: Some(ty!($ret))
608        }
609    };
610    (($($params: tt)*)) => {
611        FuncType {
612            params: ty_vec!($($params)*),
613            ret: None,
614        }
615    };
616}