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 4.12 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
    cur_offset: isize, // offset to rbp
24
25
26

    pub argument_by_reg: HashMap<MuID, P<Value>>,
    pub argument_by_stack: HashMap<MuID, P<Value>>,
qinsoon's avatar
qinsoon committed
27
    
qinsoon's avatar
qinsoon committed
28
    pub allocated: HashMap<MuID, FrameSlot>,
qinsoon's avatar
qinsoon committed
29
30
    // (callsite, destination address)
    exception_callsites: Vec<(ValueLocation, ValueLocation)>
qinsoon's avatar
qinsoon committed
31
32
}

33
34
impl fmt::Display for Frame {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35
        writeln!(f, "\nFrame for FuncVer {} {{", self.func_ver_id).unwrap();
36
37
38
39
40
        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
41
        for &(ref callsite, ref dest) in self.exception_callsites.iter() {
42
43
44
45
46
47
            writeln!(f, "    callsite: {} -> {}", callsite, dest).unwrap()
        }
        writeln!(f, "}}")
    }
}

qinsoon's avatar
qinsoon committed
48
impl Frame {
qinsoon's avatar
qinsoon committed
49
    pub fn new(func_ver_id: MuID) -> Frame {
qinsoon's avatar
qinsoon committed
50
        Frame {
qinsoon's avatar
qinsoon committed
51
            func_ver_id: func_ver_id,
qinsoon's avatar
qinsoon committed
52
            cur_offset: - (POINTER_SIZE as isize * 1), // reserve for old RBP
53
54
55
56

            argument_by_reg: HashMap::new(),
            argument_by_stack: HashMap::new(),

qinsoon's avatar
qinsoon committed
57
            allocated: HashMap::new(),
qinsoon's avatar
qinsoon committed
58
            exception_callsites: vec![]
qinsoon's avatar
qinsoon committed
59
60
61
        }
    }
    
qinsoon's avatar
qinsoon committed
62
63
64
    pub fn cur_offset(&self) -> isize {
        self.cur_offset
    }
qinsoon's avatar
qinsoon committed
65
66
67
68

    pub fn cur_size(&self) -> usize {
        self.cur_offset.abs() as usize
    }
69
70
71
72
73
74
75
76

    pub fn add_argument_by_reg(&mut self, temp: MuID, reg: P<Value>) {
        self.argument_by_reg.insert(temp, reg);
    }

    pub fn add_argument_by_stack(&mut self, temp: MuID, stack_slot: P<Value>) {
        self.argument_by_stack.insert(temp, stack_slot);
    }
qinsoon's avatar
qinsoon committed
77
    
qinsoon's avatar
qinsoon committed
78
    pub fn alloc_slot_for_callee_saved_reg(&mut self, reg: P<Value>, vm: &VM) -> P<Value> {
qinsoon's avatar
qinsoon committed
79
80
81
        let slot = self.alloc_slot(&reg, vm);
        slot.make_memory_op(reg.ty.clone(), vm)
    }
qinsoon's avatar
qinsoon committed
82
83
84
85

    pub fn remove_record_for_callee_saved_reg(&mut self, reg: MuID) {
        self.allocated.remove(&reg);
    }
qinsoon's avatar
qinsoon committed
86
87
88
89
    
    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
90
91
    }
    
qinsoon's avatar
qinsoon committed
92
93
94
95
    pub fn get_exception_callsites(&self) -> &Vec<(ValueLocation, ValueLocation)> {
        &self.exception_callsites
    }
    
qinsoon's avatar
qinsoon committed
96
    pub fn add_exception_callsite(&mut self, callsite: ValueLocation, dest: ValueLocation) {
97
        trace!("add exception callsite: {} to dest {}", callsite, dest);
qinsoon's avatar
qinsoon committed
98
        self.exception_callsites.push((callsite, dest));
qinsoon's avatar
qinsoon committed
99
100
    }
    
qinsoon's avatar
qinsoon committed
101
    fn alloc_slot(&mut self, val: &P<Value>, vm: &VM) -> &FrameSlot {
qinsoon's avatar
qinsoon committed
102
        let id = val.id();
qinsoon's avatar
qinsoon committed
103
104
105
106
107
108
109
110
111
        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
112
113
114
    }
}

qinsoon's avatar
qinsoon committed
115
#[derive(RustcEncodable, RustcDecodable, Clone)]
qinsoon's avatar
qinsoon committed
116
117
118
pub struct FrameSlot {
    pub offset: isize,
    pub value: P<Value>
qinsoon's avatar
qinsoon committed
119
120
}

121
122
123
124
125
126
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
127
128
impl FrameSlot {
    #[cfg(target_arch = "x86_64")]
qinsoon's avatar
qinsoon committed
129
    pub fn make_memory_op(&self, ty: P<MuType>, vm: &VM) -> P<Value> {
qinsoon's avatar
qinsoon committed
130
        use compiler::backend::x86_64;
qinsoon's avatar
qinsoon committed
131
132
133
134
135
136
137
138
139
140
141
142
143

        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
144
    }
145
}