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.66 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
    pub fn cur_offset(&self) -> isize {
        self.cur_offset
    }
qinsoon's avatar
qinsoon committed
58 59 60 61

    pub fn cur_size(&self) -> usize {
        self.cur_offset.abs() as usize
    }
qinsoon's avatar
qinsoon committed
62
    
qinsoon's avatar
qinsoon committed
63
    pub fn alloc_slot_for_callee_saved_reg(&mut self, reg: P<Value>, vm: &VM) -> P<Value> {
qinsoon's avatar
qinsoon committed
64 65 66
        let slot = self.alloc_slot(&reg, vm);
        slot.make_memory_op(reg.ty.clone(), vm)
    }
qinsoon's avatar
qinsoon committed
67 68 69 70

    pub fn remove_record_for_callee_saved_reg(&mut self, reg: MuID) {
        self.allocated.remove(&reg);
    }
qinsoon's avatar
qinsoon committed
71 72 73 74
    
    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
75 76
    }
    
qinsoon's avatar
qinsoon committed
77 78 79 80
    pub fn get_exception_callsites(&self) -> &Vec<(ValueLocation, ValueLocation)> {
        &self.exception_callsites
    }
    
qinsoon's avatar
qinsoon committed
81
    pub fn add_exception_callsite(&mut self, callsite: ValueLocation, dest: ValueLocation) {
82
        trace!("add exception callsite: {} to dest {}", callsite, dest);
qinsoon's avatar
qinsoon committed
83
        self.exception_callsites.push((callsite, dest));
qinsoon's avatar
qinsoon committed
84 85
    }
    
qinsoon's avatar
qinsoon committed
86
    fn alloc_slot(&mut self, val: &P<Value>, vm: &VM) -> &FrameSlot {
qinsoon's avatar
qinsoon committed
87
        let id = val.id();
qinsoon's avatar
qinsoon committed
88 89 90 91 92 93 94 95 96
        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
97 98 99
    }
}

100
#[derive(RustcEncodable, RustcDecodable, Clone)]
qinsoon's avatar
qinsoon committed
101 102 103
pub struct FrameSlot {
    pub offset: isize,
    pub value: P<Value>
qinsoon's avatar
qinsoon committed
104 105
}

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

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