1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//! Case handlers

use crate::{ControlStackFrame, ControlStackFrameType, Function, Result};

impl Function {
    /// Handle the end of the function.
    pub(crate) fn handle_return(&mut self) -> Result<()> {
        let results = self.ty.results();
        tracing::trace!("handle return, results: {results:?}");

        self.masm.main_return(results)
    }

    /// Handle the return of a call.
    pub(crate) fn handle_call_return(&mut self) -> Result<()> {
        let results = self.ty.results();
        tracing::trace!("handle call return: {:?}", results);

        self.masm.call_return(results)
    }

    /// Handle the popping of a frame.
    ///
    /// TODO: validate stack IO for all frames (#59)
    pub(crate) fn handle_frame_popping(&mut self, frame: ControlStackFrame) -> Result<()> {
        match frame.ty {
            ControlStackFrameType::If(true) => {
                // TODO: fix this for nested if-else.
                self.handle_return()
            }
            ControlStackFrameType::Block => self.masm._jumpdest(),
            ControlStackFrameType::Loop => Ok(()),
            _ => self.handle_jumpdest(frame.original_pc_offset),
        }
    }

    /// Handle jumpdest.
    pub(crate) fn handle_jumpdest(&mut self, original_pc: u16) -> Result<()> {
        self.table.label(original_pc, self.masm.pc_offset());

        // TODO: Check the stack output and make decisions
        // how to handle the results.

        // Emit JUMPDEST after at the end of the control flow.
        self.masm._jumpdest()?;

        Ok(())
    }
}