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

henrythasler / rust-tiny-wasm / 24211213782

09 Apr 2026 08:15PM UTC coverage: 83.452% (-0.1%) from 83.564%
24211213782

push

github

henrythasler
if-else-prototype

62 of 69 new or added lines in 5 files covered. (89.86%)

41 existing lines in 6 files now uncovered.

1402 of 1680 relevant lines covered (83.45%)

26.33 hits per line

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

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

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

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

23
    let initial_size = machinecode.len();
65✔
24
    let mut register_pool = RegisterPool::default();
65✔
25

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

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

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

44
    if !locals.is_empty() {
65✔
45
        variables.extend(save_locals_to_stack(&mut stack_offset, locals, machinecode));
8✔
46
    }
57✔
47

48
    'expression: while !reader.eof() {
285✔
49
        let index = reader.original_position();
285✔
50
        let op = reader.read().unwrap();
285✔
51
        match op {
285✔
52
            Operator::End => {
53
                if compile_end(&mut control_stack, &mut value_stack, machinecode) {
66✔
54
                    break 'expression;
64✔
55
                }
2✔
56
            }
57
            Operator::Return => {
4✔
58
                compile_return(&mut control_stack, machinecode);
4✔
59
            }
4✔
60
            Operator::If { blockty } => {
2✔
61
                compile_if(
2✔
62
                    blockty,
2✔
63
                    &mut control_stack,
2✔
64
                    &mut value_stack,
2✔
65
                    &mut register_pool,
2✔
66
                    machinecode,
2✔
67
                );
2✔
68
            }
2✔
69
            Operator::Else => {
2✔
70
                compile_else(
2✔
71
                    &mut control_stack,
2✔
72
                    &mut value_stack,
2✔
73
                    &mut register_pool,
2✔
74
                    machinecode,
2✔
75
                );
2✔
76
            }
2✔
77
            Operator::I64LtS => {
78
                compile_relop(&op, &mut value_stack, &mut register_pool, machinecode)
2✔
79
            }
80
            Operator::I32Const { value } => {
16✔
81
                compile_const(
16✔
82
                    &op,
16✔
83
                    value,
16✔
84
                    &mut value_stack,
16✔
85
                    &mut register_pool,
16✔
86
                    machinecode,
16✔
87
                );
16✔
88
            }
16✔
89
            Operator::I64Const { value } => {
24✔
90
                compile_const(
24✔
91
                    &op,
24✔
92
                    value,
24✔
93
                    &mut value_stack,
24✔
94
                    &mut register_pool,
24✔
95
                    machinecode,
24✔
96
                );
24✔
97
            }
24✔
98
            Operator::LocalGet { local_index } => {
96✔
99
                let var = variables.get(local_index as usize).unwrap();
96✔
100
                compile_local_get(
96✔
101
                    var,
96✔
102
                    var.offset,
96✔
103
                    &mut value_stack,
96✔
104
                    &mut register_pool,
96✔
105
                    machinecode,
96✔
106
                );
96✔
107
            }
96✔
108
            Operator::LocalSet { local_index } => {
50✔
109
                let var = variables.get(local_index as usize).unwrap();
50✔
110
                compile_local_set(
50✔
111
                    var,
50✔
112
                    var.offset,
50✔
113
                    &mut value_stack,
50✔
114
                    &mut register_pool,
50✔
115
                    machinecode,
50✔
116
                );
50✔
117
            }
50✔
118
            Operator::LocalTee { local_index } => {
2✔
119
                let var = variables.get(local_index as usize).unwrap();
2✔
120
                compile_local_tee(var, var.offset, &mut value_stack, machinecode);
2✔
121
            }
2✔
122
            Operator::I32Add
123
            | Operator::I64Add
124
            | Operator::I32Sub
125
            | Operator::I64Sub
126
            | Operator::I32Mul
127
            | Operator::I64Mul => {
20✔
128
                compile_binop(&op, &mut value_stack, &mut register_pool, machinecode);
20✔
129
            }
20✔
130
            _ => {
131
                return Err(TinyWasmError::Compiler(format!(
1✔
132
                    "unsupported instruction: {:?} at position {}",
1✔
133
                    op, index
1✔
134
                )));
1✔
135
            }
136
        }
137
    }
138

139
    // move result values to result registers according to Aarch64 Procedure Call Standard (X0..X7)
140
    // X0: Result, X1: Tag (0=Ok, 1=Trap)
141
    if !func_type.results().is_empty() {
64✔
142
        load_results(&mut value_stack, func_type.results().len(), machinecode)?;
60✔
143
    } else {
4✔
144
        // Result=0
4✔
145
        machinecode.push(processing::mov_reg(Reg::X0, Reg::XZR, RegSize::Reg64bit));
4✔
146
        // Tag=Ok (0)
4✔
147
        machinecode.push(processing::mov_reg(Reg::X1, Reg::XZR, RegSize::Reg64bit));
4✔
148
    }
4✔
149

150
    // restore initial state before returning to the caller
151
    emit_epilogue(stack_size, machinecode);
64✔
152

153
    // add padding to INSTRUCTION_SIZE to align subsequent functions to the correct size
154
    let padding_instructions =
64✔
155
        ((machinecode.len() * INSTRUCTION_SIZE) % mem::align_of::<fn()>()) / INSTRUCTION_SIZE;
64✔
156
    for _ in 0..padding_instructions {
64✔
157
        machinecode.push(hint::nop());
32✔
158
    }
32✔
159

160
    Ok(machinecode.len() - initial_size)
64✔
161
}
65✔
162

163
pub fn map_op_to_valtype(op: &Operator) -> ValType {
62✔
164
    match op {
62✔
165
        Operator::I32Add
166
        | Operator::I32Sub
167
        | Operator::I32Mul
168
        | Operator::I32Const { .. }
169
        | Operator::I32LtS => ValType::I32,
28✔
170
        Operator::I64Add
171
        | Operator::I64Sub
172
        | Operator::I64Mul
173
        | Operator::I64Const { .. }
174
        | Operator::I64LtS => ValType::I64,
34✔
UNCOV
175
        _ => panic!("Operator '{:?}' not supported", op),
×
176
    }
177
}
62✔
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