• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

henrythasler / rust-tiny-wasm / 26326261664

23 May 2026 06:53AM UTC coverage: 95.514% (+0.09%) from 95.42%
26326261664

push

github

henrythasler
implement div instruction mvp

Co-authored-by: Copilot <copilot@github.com>

39 of 39 new or added lines in 3 files covered. (100.0%)

2 existing lines in 2 files now uncovered.

1682 of 1761 relevant lines covered (95.51%)

65.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.43
/src/compiler/function.rs
1
use super::*;
2

3
pub fn compile_function(
139✔
4
    reader: &mut wasmparser::OperatorsReader<'_>,
139✔
5
    func_type: &wasmparser::FuncType,
139✔
6
    locals: &[(u32, ValType)],
139✔
7
    machinecode: &mut Vec<u32>,
139✔
8
) -> Result<usize> {
139✔
9
    // Value stack starts empty
10
    let mut value_stack: Vec<StackElement> = vec![];
139✔
11

12
    // Control stack is initialized with the (implicit) outer func-block
13
    let mut control_stack: Vec<ControlFrame> = vec![ControlFrame {
139✔
14
        opcode: Opcode::Func,
139✔
15
        start_types: func_type.params().to_vec(),
139✔
16
        end_types: func_type.results().to_vec(),
139✔
17
        stack_height: value_stack.len(),
139✔
18
        value_stack: None,
139✔
19
        register_index: None,
139✔
20
        result_register: None,
139✔
21
        machinecode_offset: machinecode.len(),
139✔
22
        patches: vec![],
139✔
23
    }];
139✔
24

25
    let initial_size = machinecode.len();
139✔
26
    let mut register_pool = RegisterPool::new();
139✔
27

28
    // calculate initial stack size from all parameters and locals
29
    let (_variables_size, stack_size) = get_aligned_stack_size(func_type, locals);
139✔
30
    // println!("{} {:?}", _variables_size, stack_size);
31

32
    // every functions starts with an epilogue to save the initial state and create a new stack frame
33
    emit_prologue(stack_size, &mut register_pool, machinecode);
139✔
34

35
    let mut variables: Vec<LocalVar> = vec![];
139✔
36
    let mut stack_offset = 0;
139✔
37
    // save parameters to stack
38
    if !func_type.params().is_empty() {
139✔
39
        variables.extend(save_parameters_to_stack(
74✔
40
            &mut stack_offset,
74✔
41
            func_type.params(),
74✔
42
            machinecode,
74✔
43
        ));
74✔
44
    }
74✔
45

46
    if !locals.is_empty() {
139✔
47
        variables.extend(save_locals_to_stack(&mut stack_offset, locals, machinecode));
16✔
48
    }
123✔
49

50
    'expression: while !reader.eof() {
1,059✔
51
        let index = reader.original_position();
1,059✔
52
        let op = reader.read().unwrap();
1,059✔
53
        match op {
1,059✔
54
            Operator::Drop => compile_drop(&mut value_stack, &mut register_pool),
56✔
55
            Operator::Return => compile_return(&mut control_stack, &value_stack, machinecode),
24✔
56
            Operator::Block { blockty } => {
54✔
57
                compile_block(
54✔
58
                    blockty,
54✔
59
                    &mut control_stack,
54✔
60
                    &mut value_stack,
54✔
61
                    &mut register_pool,
54✔
62
                    machinecode,
54✔
63
                );
54✔
64
            }
54✔
65
            Operator::Br { relative_depth } => {
14✔
66
                compile_br(
14✔
67
                    relative_depth,
14✔
68
                    &mut control_stack,
14✔
69
                    &value_stack,
14✔
70
                    // &mut register_pool,
14✔
71
                    machinecode,
14✔
72
                );
14✔
73
            }
14✔
74
            Operator::BrIf { relative_depth } => {
54✔
75
                compile_brif(
54✔
76
                    relative_depth,
54✔
77
                    &mut control_stack,
54✔
78
                    &mut value_stack,
54✔
79
                    &mut register_pool,
54✔
80
                    machinecode,
54✔
81
                );
54✔
82
            }
54✔
83
            Operator::Loop { blockty } => {
8✔
84
                compile_loop(
8✔
85
                    blockty,
8✔
86
                    &mut control_stack,
8✔
87
                    &mut value_stack,
8✔
88
                    &mut register_pool,
8✔
89
                    machinecode,
8✔
90
                );
8✔
91
            }
8✔
92
            Operator::If { blockty } => {
20✔
93
                compile_if(
20✔
94
                    blockty,
20✔
95
                    &mut control_stack,
20✔
96
                    &mut value_stack,
20✔
97
                    &mut register_pool,
20✔
98
                    machinecode,
20✔
99
                );
20✔
100
            }
20✔
101
            Operator::Else => {
16✔
102
                compile_else(
16✔
103
                    &mut control_stack,
16✔
104
                    &mut value_stack,
16✔
105
                    &mut register_pool,
16✔
106
                    machinecode,
16✔
107
                );
16✔
108
            }
16✔
109
            Operator::End => {
110
                if compile_end(
220✔
111
                    &mut control_stack,
220✔
112
                    &mut value_stack,
220✔
113
                    &mut register_pool,
220✔
114
                    machinecode,
220✔
115
                ) {
116
                    break 'expression;
138✔
117
                }
82✔
118
            }
119
            Operator::I32LtS | Operator::I64LtS | Operator::I32LeU | Operator::I64LeU => {
120
                compile_relop(&op, &mut value_stack, &mut register_pool, machinecode)
32✔
121
            }
122
            Operator::I32Eqz | Operator::I64Eqz => {
123
                compile_testop(&op, &mut value_stack, machinecode)
2✔
124
            }
125
            Operator::I32Const { value } => {
172✔
126
                compile_const(
172✔
127
                    &op,
172✔
128
                    value,
172✔
129
                    &mut value_stack,
172✔
130
                    &mut register_pool,
172✔
131
                    machinecode,
172✔
132
                );
172✔
133
            }
172✔
134
            Operator::I64Const { value } => {
80✔
135
                compile_const(
80✔
136
                    &op,
80✔
137
                    value,
80✔
138
                    &mut value_stack,
80✔
139
                    &mut register_pool,
80✔
140
                    machinecode,
80✔
141
                );
80✔
142
            }
80✔
143
            Operator::LocalGet { local_index } => {
176✔
144
                let var = variables.get(local_index as usize).unwrap();
176✔
145
                compile_local_get(
176✔
146
                    var,
176✔
147
                    var.offset,
176✔
148
                    &mut value_stack,
176✔
149
                    &mut register_pool,
176✔
150
                    machinecode,
176✔
151
                );
176✔
152
            }
176✔
153
            Operator::LocalSet { local_index } => {
56✔
154
                let var = variables.get(local_index as usize).unwrap();
56✔
155
                compile_local_set(
56✔
156
                    var,
56✔
157
                    var.offset,
56✔
158
                    &mut value_stack,
56✔
159
                    &mut register_pool,
56✔
160
                    machinecode,
56✔
161
                );
56✔
162
            }
56✔
163
            Operator::LocalTee { local_index } => {
6✔
164
                let var = variables.get(local_index as usize).unwrap();
6✔
165
                compile_local_tee(var, var.offset, &mut value_stack, machinecode);
6✔
166
            }
6✔
167
            Operator::I32Add
168
            | Operator::I64Add
169
            | Operator::I32Sub
170
            | Operator::I64Sub
171
            | Operator::I32Mul
172
            | Operator::I64Mul
173
            | Operator::I32DivU
174
            | Operator::I64DivU
175
            | Operator::I32DivS
176
            | Operator::I64DivS => {
60✔
177
                compile_binop(&op, &mut value_stack, &mut register_pool, machinecode);
60✔
178
            }
60✔
179
            Operator::I32Ctz | Operator::I64Ctz => {
8✔
180
                compile_unop(&op, &mut value_stack, machinecode);
8✔
181
            }
8✔
182
            _ => {
183
                return Err(TinyWasmError::Compiler(format!(
1✔
184
                    "unsupported instruction: {:?} at position {}",
1✔
185
                    op, index
1✔
186
                )));
1✔
187
            }
188
        }
189
    }
190

191
    // move result values to result registers according to Aarch64 Procedure Call Standard (X0..X7)
192
    // X0: Result, X1: Tag (0=Ok, 1=Trap)
193
    if !func_type.results().is_empty() {
138✔
194
        load_results(&mut value_stack, func_type.results().len(), machinecode)?;
128✔
195
    } else {
10✔
196
        // Result=0
10✔
197
        machinecode.push(processing::mov_reg(Reg::X0, Reg::XZR, RegSize::Reg64bit));
10✔
198
        // Tag=Ok (0)
10✔
199
        machinecode.push(processing::mov_reg(Reg::X1, Reg::XZR, RegSize::Reg64bit));
10✔
200
    }
10✔
201

202
    // restore initial state before returning to the caller
203
    emit_epilogue(stack_size, machinecode);
138✔
204

205
    // add padding to INSTRUCTION_SIZE to align subsequent functions to the correct size
206
    let padding_instructions =
138✔
207
        ((machinecode.len() * INSTRUCTION_SIZE) % mem::align_of::<fn()>()) / INSTRUCTION_SIZE;
138✔
208
    for _ in 0..padding_instructions {
138✔
209
        machinecode.push(hint::nop());
92✔
210
    }
92✔
211

212
    Ok(machinecode.len() - initial_size)
138✔
213
}
139✔
214

215
pub fn map_op_to_valtype(op: &Operator) -> ValType {
354✔
216
    match op {
354✔
217
        Operator::I32Add
218
        | Operator::I32Sub
219
        | Operator::I32Mul
220
        | Operator::I32Const { .. }
221
        | Operator::I32Ctz
222
        | Operator::I32LtS
223
        | Operator::I32LeU
224
        | Operator::I32Eqz
225
        | Operator::I32DivS
226
        | Operator::I32DivU => ValType::I32,
230✔
227
        Operator::I64Add
228
        | Operator::I64Sub
229
        | Operator::I64Mul
230
        | Operator::I64Const { .. }
231
        | Operator::I64Ctz
232
        | Operator::I64LtS
233
        | Operator::I64LeU
234
        | Operator::I64Eqz
235
        | Operator::I64DivS
236
        | Operator::I64DivU => ValType::I64,
124✔
UNCOV
237
        _ => panic!("Operator '{:?}' not supported", op),
×
238
    }
239
}
354✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc