1
use wasm_encoder::{BlockType, Function, Instruction, MemArg, ValType};
2

            
3
pub struct FunctionEmitter {
4
    func: Function,
5
}
6

            
7
impl FunctionEmitter {
8
    pub fn new() -> Self {
9
        Self {
10
            func: Function::new([]),
11
        }
12
    }
13

            
14
12113
    pub fn new_with_locals(locals: &[(u32, ValType)]) -> Self {
15
12113
        Self {
16
12113
            func: Function::new(locals.iter().copied()),
17
12113
        }
18
12113
    }
19

            
20
204
    pub fn memory_init(&mut self, data_idx: u32, dst: u32, len: u32) {
21
204
        self.func.instruction(&Instruction::I32Const(dst as i32));
22
204
        self.func.instruction(&Instruction::I32Const(0)); // src offset in data segment
23
204
        self.func.instruction(&Instruction::I32Const(len as i32));
24
204
        self.func.instruction(&Instruction::MemoryInit {
25
204
            mem: 0,
26
204
            data_index: data_idx,
27
204
        });
28
204
    }
29

            
30
41430
    pub fn local_get(&mut self, idx: u32) {
31
41430
        self.func.instruction(&Instruction::LocalGet(idx));
32
41430
    }
33

            
34
32828
    pub fn local_set(&mut self, idx: u32) {
35
32828
        self.func.instruction(&Instruction::LocalSet(idx));
36
32828
    }
37

            
38
42042
    pub fn i32_const(&mut self, value: i32) {
39
42042
        self.func.instruction(&Instruction::I32Const(value));
40
42042
    }
41

            
42
20715
    pub fn i32_add(&mut self) {
43
20715
        self.func.instruction(&Instruction::I32Add);
44
20715
    }
45

            
46
6905
    pub fn i32_ge_u(&mut self) {
47
6905
        self.func.instruction(&Instruction::I32GeU);
48
6905
    }
49

            
50
6905
    pub fn array_new_data(&mut self, type_idx: u32, data_idx: u32) {
51
6905
        self.func.instruction(&Instruction::ArrayNewData {
52
6905
            array_type_index: type_idx,
53
6905
            array_data_index: data_idx,
54
6905
        });
55
6905
    }
56

            
57
6905
    pub fn array_get_u(&mut self, type_idx: u32) {
58
6905
        self.func.instruction(&Instruction::ArrayGetU(type_idx));
59
6905
    }
60

            
61
6905
    pub fn block_start(&mut self) {
62
6905
        self.func.instruction(&Instruction::Block(BlockType::Empty));
63
6905
    }
64

            
65
6905
    pub fn loop_start(&mut self) {
66
6905
        self.func.instruction(&Instruction::Loop(BlockType::Empty));
67
6905
    }
68

            
69
13810
    pub fn block_end(&mut self) {
70
13810
        self.func.instruction(&Instruction::End);
71
13810
    }
72

            
73
6905
    pub fn br(&mut self, depth: u32) {
74
6905
        self.func.instruction(&Instruction::Br(depth));
75
6905
    }
76

            
77
6905
    pub fn br_if(&mut self, depth: u32) {
78
6905
        self.func.instruction(&Instruction::BrIf(depth));
79
6905
    }
80

            
81
12317
    pub fn call(&mut self, func_idx: u32) {
82
12317
        self.func.instruction(&Instruction::Call(func_idx));
83
12317
    }
84

            
85
44198
    pub fn store_u8_dynamic(&mut self, local_base: u32, offset: u32, value: u8) {
86
44198
        self.func.instruction(&Instruction::LocalGet(local_base));
87
44198
        self.func.instruction(&Instruction::I32Const(offset as i32));
88
44198
        self.func.instruction(&Instruction::I32Add);
89
44198
        self.func
90
44198
            .instruction(&Instruction::I32Const(i32::from(value)));
91
44198
        self.func.instruction(&Instruction::I32Store8(MemArg {
92
44198
            offset: 0,
93
44198
            align: 0,
94
44198
            memory_index: 0,
95
44198
        }));
96
44198
    }
97

            
98
99658
    pub fn store_i32_dynamic(&mut self, local_base: u32, offset: u32, value: i32) {
99
99658
        self.func.instruction(&Instruction::LocalGet(local_base));
100
99658
        self.func.instruction(&Instruction::I32Const(offset as i32));
101
99658
        self.func.instruction(&Instruction::I32Add);
102
99658
        self.func.instruction(&Instruction::I32Const(value));
103
99658
        self.func.instruction(&Instruction::I32Store(MemArg {
104
99658
            offset: 0,
105
99658
            align: 2,
106
99658
            memory_index: 0,
107
99658
        }));
108
99658
    }
109

            
110
19798
    pub fn store_i64_dynamic(&mut self, local_base: u32, offset: u32, value: i64) {
111
19798
        self.func.instruction(&Instruction::LocalGet(local_base));
112
19798
        self.func.instruction(&Instruction::I32Const(offset as i32));
113
19798
        self.func.instruction(&Instruction::I32Add);
114
19798
        self.func.instruction(&Instruction::I64Const(value));
115
19798
        self.func.instruction(&Instruction::I64Store(MemArg {
116
19798
            offset: 0,
117
19798
            align: 3,
118
19798
            memory_index: 0,
119
19798
        }));
120
19798
    }
121

            
122
6905
    pub fn i32_store8_raw(&mut self) {
123
6905
        self.func.instruction(&Instruction::I32Store8(MemArg {
124
6905
            offset: 0,
125
6905
            align: 0,
126
6905
            memory_index: 0,
127
6905
        }));
128
6905
    }
129

            
130
11058
    pub fn end(&mut self) {
131
11058
        self.func.instruction(&Instruction::End);
132
11058
    }
133

            
134
11058
    pub fn finish(self) -> Function {
135
11058
        self.func
136
11058
    }
137
}
138

            
139
impl Default for FunctionEmitter {
140
    fn default() -> Self {
141
        Self::new()
142
    }
143
}