frame.rs 2.19 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

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

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

qinsoon's avatar
qinsoon committed
18
19
20
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};

#[derive(RustcEncodable, RustcDecodable)]
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
28
}

impl Frame {
qinsoon's avatar
qinsoon committed
29
    pub fn new(func_ver_id: MuID) -> Frame {
qinsoon's avatar
qinsoon committed
30
        Frame {
qinsoon's avatar
qinsoon committed
31
            func_ver_id: func_ver_id,
qinsoon's avatar
qinsoon committed
32
33
            cur_offset: - (POINTER_SIZE as isize * 1), // reserve for old RBP
            allocated: HashMap::new()
qinsoon's avatar
qinsoon committed
34
35
36
37
        }
    }
    
    pub fn alloc_slot_for_callee_saved_reg(&mut self, reg: P<Value>, vm: &VM) -> P<Value> {
qinsoon's avatar
qinsoon committed
38
39
40
41
42
43
44
        let slot = self.alloc_slot(&reg, vm);
        slot.make_memory_op(reg.ty.clone(), vm)
    }
    
    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
45
46
    }
    
qinsoon's avatar
qinsoon committed
47
    fn alloc_slot(&mut self, val: &P<Value>, vm: &VM) -> &FrameSlot {
qinsoon's avatar
qinsoon committed
48
        let id = val.id();
qinsoon's avatar
qinsoon committed
49
50
51
52
53
54
55
56
57
        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
58
59
60
    }
}

qinsoon's avatar
qinsoon committed
61
#[derive(RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
62
63
64
pub struct FrameSlot {
    pub offset: isize,
    pub value: P<Value>
qinsoon's avatar
qinsoon committed
65
66
67
68
}

impl FrameSlot {
    #[cfg(target_arch = "x86_64")]
qinsoon's avatar
qinsoon committed
69
    pub fn make_memory_op(&self, ty: P<MuType>, vm: &VM) -> P<Value> {
qinsoon's avatar
qinsoon committed
70
        use compiler::backend::x86_64;
qinsoon's avatar
qinsoon committed
71
72
73
74
75
76
77
78
79
80
81
82
83

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