GitLab will be upgraded on 30 Jan 2023 from 2.00 pm (AEDT) to 3.00 pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

frame.rs 3.58 KB
Newer Older
qinsoon's avatar
qinsoon committed
1
2
use ast::ir::*;
use ast::ptr::*;
qinsoon's avatar
qinsoon committed
3
use ast::types::*;
qinsoon's avatar
qinsoon committed
4
use runtime::ValueLocation;
qinsoon's avatar
qinsoon committed
5

6
use std::fmt;
qinsoon's avatar
qinsoon committed
7
use std::collections::HashMap;
qinsoon's avatar
qinsoon committed
8
use utils::POINTER_SIZE;
qinsoon's avatar
qinsoon committed
9
use vm::VM;
qinsoon's avatar
qinsoon committed
10
11
12
13
14
15
16
17
18
19

// | previous frame ...
// |---------------
// | return address
// | old RBP        <- RBP
// | callee saved
// | spilled
// |---------------
// | alloca area

qinsoon's avatar
qinsoon committed
20
#[derive(RustcEncodable, RustcDecodable, Clone)]
qinsoon's avatar
qinsoon committed
21
pub struct Frame {
qinsoon's avatar
qinsoon committed
22
    func_ver_id: MuID,
qinsoon's avatar
qinsoon committed
23
24
    cur_offset: isize, // offset to rbp
    
qinsoon's avatar
qinsoon committed
25
    pub allocated: HashMap<MuID, FrameSlot>,
qinsoon's avatar
qinsoon committed
26
27
    // (callsite, destination address)
    exception_callsites: Vec<(ValueLocation, ValueLocation)>
qinsoon's avatar
qinsoon committed
28
29
}

30
31
32
33
34
35
36
37
impl fmt::Display for Frame {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "Frame for FuncVer {} {{", self.func_ver_id).unwrap();
        writeln!(f, "  allocated slots:").unwrap();
        for slot in self.allocated.values() {
            writeln!(f, "    {}", slot).unwrap();
        }
        writeln!(f, "  exception callsites:").unwrap();
qinsoon's avatar
qinsoon committed
38
        for &(ref callsite, ref dest) in self.exception_callsites.iter() {
39
40
41
42
43
44
            writeln!(f, "    callsite: {} -> {}", callsite, dest).unwrap()
        }
        writeln!(f, "}}")
    }
}

qinsoon's avatar
qinsoon committed
45
impl Frame {
qinsoon's avatar
qinsoon committed
46
    pub fn new(func_ver_id: MuID) -> Frame {
qinsoon's avatar
qinsoon committed
47
        Frame {
qinsoon's avatar
qinsoon committed
48
            func_ver_id: func_ver_id,
qinsoon's avatar
qinsoon committed
49
            cur_offset: - (POINTER_SIZE as isize * 1), // reserve for old RBP
qinsoon's avatar
qinsoon committed
50
            allocated: HashMap::new(),
qinsoon's avatar
qinsoon committed
51
            exception_callsites: vec![]
qinsoon's avatar
qinsoon committed
52
53
54
        }
    }
    
qinsoon's avatar
qinsoon committed
55
56
57
58
    pub fn cur_offset(&self) -> isize {
        self.cur_offset
    }
    
qinsoon's avatar
qinsoon committed
59
    pub fn alloc_slot_for_callee_saved_reg(&mut self, reg: P<Value>, vm: &VM) -> P<Value> {
qinsoon's avatar
qinsoon committed
60
61
62
        let slot = self.alloc_slot(&reg, vm);
        slot.make_memory_op(reg.ty.clone(), vm)
    }
qinsoon's avatar
qinsoon committed
63
64
65
66

    pub fn remove_record_for_callee_saved_reg(&mut self, reg: MuID) {
        self.allocated.remove(&reg);
    }
qinsoon's avatar
qinsoon committed
67
68
69
70
    
    pub fn alloc_slot_for_spilling(&mut self, reg: P<Value>, vm: &VM) -> P<Value> {
        let slot = self.alloc_slot(&reg, vm);
        slot.make_memory_op(reg.ty.clone(), vm)
qinsoon's avatar
qinsoon committed
71
72
    }
    
qinsoon's avatar
qinsoon committed
73
74
75
76
    pub fn get_exception_callsites(&self) -> &Vec<(ValueLocation, ValueLocation)> {
        &self.exception_callsites
    }
    
qinsoon's avatar
qinsoon committed
77
    pub fn add_exception_callsite(&mut self, callsite: ValueLocation, dest: ValueLocation) {
78
        trace!("add exception callsite: {} to dest {}", callsite, dest);
qinsoon's avatar
qinsoon committed
79
        self.exception_callsites.push((callsite, dest));
qinsoon's avatar
qinsoon committed
80
81
    }
    
qinsoon's avatar
qinsoon committed
82
    fn alloc_slot(&mut self, val: &P<Value>, vm: &VM) -> &FrameSlot {
qinsoon's avatar
qinsoon committed
83
        let id = val.id();
qinsoon's avatar
qinsoon committed
84
85
86
87
88
89
90
91
92
        let ret = FrameSlot {
            offset: self.cur_offset,
            value: val.clone()
        };
        
        self.cur_offset -= vm.get_type_size(val.ty.id()) as isize;
        
        self.allocated.insert(id, ret);
        self.allocated.get(&id).unwrap()
qinsoon's avatar
qinsoon committed
93
94
95
    }
}

qinsoon's avatar
qinsoon committed
96
#[derive(RustcEncodable, RustcDecodable, Clone)]
qinsoon's avatar
qinsoon committed
97
98
99
pub struct FrameSlot {
    pub offset: isize,
    pub value: P<Value>
qinsoon's avatar
qinsoon committed
100
101
}

102
103
104
105
106
107
impl fmt::Display for FrameSlot {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}(RBP): {}", self.offset, self.value)
    }
}

qinsoon's avatar
qinsoon committed
108
109
impl FrameSlot {
    #[cfg(target_arch = "x86_64")]
qinsoon's avatar
qinsoon committed
110
    pub fn make_memory_op(&self, ty: P<MuType>, vm: &VM) -> P<Value> {
qinsoon's avatar
qinsoon committed
111
        use compiler::backend::x86_64;
qinsoon's avatar
qinsoon committed
112
113
114
115
116
117
118
119
120
121
122
123
124

        P(Value{
            hdr: MuEntityHeader::unnamed(vm.next_id()),
            ty: ty.clone(),
            v: Value_::Memory(
                MemoryLocation::Address{
                    base: x86_64::RBP.clone(),
                    offset: Some(Value::make_int_const(vm.next_id(), self.offset as u64)),
                    index: None,
                    scale: None
                }
            )
        })
qinsoon's avatar
qinsoon committed
125
126
    }
}