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
50
51
52
53
54
55
56
57
use crate::{
    backend::riscv::from_ir::{function::FunctionCompileContext, register_assign::RegisterAssign},
    ir,
};

/// Emit assembly code for a [`ir::statement::Load`].
pub fn emit_code(
    statement: &ir::function::statement::Load,
    ctx: &mut FunctionCompileContext,
) -> String {
    let ir::function::statement::Load {
        to,
        data_type: _,
        from,
    } = statement;
    let mut result = String::new();
    let from_stack_offset = match from {
        ir::quantity::Quantity::RegisterName(local) => {
            let physical_register = ctx.local_assign.get(local).unwrap();
            match physical_register {
                RegisterAssign::Register(_register) => {
                    // unreachable!() ?
                    todo!()
                }
                RegisterAssign::StackRef(stack_offset) => stack_offset,
                RegisterAssign::StackValue(_) => {
                    // unreachable!() ?
                    todo!()
                }
                RegisterAssign::MultipleRegisters(_) => unreachable!(),
            }
        }
        ir::quantity::Quantity::GlobalVariableName(_global) => todo!(),
        ir::quantity::Quantity::NumberLiteral(_literal) => unreachable!(),
    };
    let to_physical = ctx.local_assign.get(to).unwrap();
    let to_register = match to_physical {
        RegisterAssign::Register(register) => register.to_string(),
        RegisterAssign::StackValue(_) => "t0".to_string(),
        RegisterAssign::StackRef(_) => unreachable!(),
        RegisterAssign::MultipleRegisters(registers) => {
            for (i, register) in registers.iter().enumerate() {
                result.push_str(&format!(
                    "    lw {}, {}(sp)\n",
                    register,
                    from_stack_offset + i * 4
                ));
            }
            return result;
        }
    };
    result.push_str(&format!("    lw {to_register}, {from_stack_offset}(sp)\n"));
    if let RegisterAssign::StackValue(stack_offset) = to_physical {
        result.push_str(&format!("    sw {to_register}, {stack_offset}(sp)\n"));
    }
    result
}