GitLab will be upgraded to the 12.10.14-ce.0 on 28 Sept 2020 at 2.00pm (AEDT) to 2.30pm (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

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

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