WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.6% of users enabled 2FA.

mod.rs 6.9 KB
Newer Older
1
pub mod inst_sel;
2
pub mod reg_alloc;
3
pub mod peephole_opt;
4
pub mod code_emission;
5

qinsoon's avatar
qinsoon committed
6
use utils::ByteSize;
qinsoon's avatar
qinsoon committed
7

8 9 10
pub type Word = usize;
pub const WORD_SIZE : ByteSize = 8;

11 12
pub const AOT_EMIT_CONTEXT_FILE : &'static str = "context.s";

qinsoon's avatar
qinsoon committed
13 14 15 16
// this is not full name, but pro/epilogue name is generated from this
pub const PROLOGUE_BLOCK_NAME: &'static str = "prologue";
pub const EPILOGUE_BLOCK_NAME: &'static str = "epilogue";

qinsoon's avatar
qinsoon committed
17 18 19
pub type Reg<'a> = &'a P<Value>;
pub type Mem<'a> = &'a P<Value>;

qinsoon's avatar
qinsoon committed
20
// X86_64
qinsoon's avatar
qinsoon committed
21

22
#[cfg(target_arch = "x86_64")]
23
#[path = "arch/x86_64/mod.rs"]
24
pub mod x86_64;
25

qinsoon's avatar
qinsoon committed
26 27
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::estimate_insts_for_ir;
qinsoon's avatar
qinsoon committed
28
#[cfg(target_arch = "x86_64")]
qinsoon's avatar
qinsoon committed
29
pub use compiler::backend::x86_64::init_machine_regs_for_func;
30 31
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::is_aliased;
qinsoon's avatar
qinsoon committed
32
#[cfg(target_arch = "x86_64")]
qinsoon's avatar
qinsoon committed
33
pub use compiler::backend::x86_64::get_color_for_precolored;
qinsoon's avatar
qinsoon committed
34
#[cfg(target_arch = "x86_64")]
qinsoon's avatar
qinsoon committed
35
pub use compiler::backend::x86_64::number_of_regs_in_group;
qinsoon's avatar
qinsoon committed
36
#[cfg(target_arch = "x86_64")]
qinsoon's avatar
qinsoon committed
37 38 39
pub use compiler::backend::x86_64::number_of_all_regs;
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::all_regs;
40
#[cfg(target_arch = "x86_64")]
41 42
pub use compiler::backend::x86_64::all_usable_regs;
#[cfg(target_arch = "x86_64")]
43
pub use compiler::backend::x86_64::pick_group_for_reg;
44 45
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::is_callee_saved;
46 47 48 49
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::emit_code;
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::emit_context;
50 51
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::spill_rewrite;
qinsoon's avatar
qinsoon committed
52

qinsoon's avatar
qinsoon committed
53 54
// ARM

qinsoon's avatar
qinsoon committed
55 56 57
#[cfg(target_arch = "arm")]
#[path = "arch/arm/mod.rs"]
mod arm;
qinsoon's avatar
qinsoon committed
58 59 60

// common data structure with target specific info

qinsoon's avatar
qinsoon committed
61
use vm::VM;
qinsoon's avatar
qinsoon committed
62 63
use ast::types::*;
use ast::ptr::*;
64
use ast::ir::*;
qinsoon's avatar
qinsoon committed
65
pub fn resolve_backend_type_info (ty: &MuType, vm: &VM) -> BackendTypeInfo {
qinsoon's avatar
qinsoon committed
66
    match ty.v {
qinsoon's avatar
qinsoon committed
67
        // integral
qinsoon's avatar
qinsoon committed
68
        MuType_::Int(size_in_bit) => {
qinsoon's avatar
qinsoon committed
69
            match size_in_bit {
qinsoon's avatar
qinsoon committed
70
                1  => BackendTypeInfo{size: 1, alignment: 1, struct_layout: None},
qinsoon's avatar
qinsoon committed
71 72 73 74 75 76 77 78
                8  => BackendTypeInfo{size: 1, alignment: 1, struct_layout: None},
                16 => BackendTypeInfo{size: 2, alignment: 2, struct_layout: None},
                32 => BackendTypeInfo{size: 4, alignment: 4, struct_layout: None},
                64 => BackendTypeInfo{size: 8, alignment: 8, struct_layout: None},
                _ => unimplemented!()
            }
        },
        // pointer of any type
qinsoon's avatar
qinsoon committed
79 80 81 82 83 84 85 86 87
        MuType_::Ref(_)
        | MuType_::IRef(_)
        | MuType_::WeakRef(_)
        | MuType_::UPtr(_)
        | MuType_::FuncRef(_)
        | MuType_::UFuncPtr(_)
        | MuType_::Tagref64
        | MuType_::ThreadRef
        | MuType_::StackRef => BackendTypeInfo{size: 8, alignment: 8, struct_layout: None},
qinsoon's avatar
qinsoon committed
88
        // floating point
qinsoon's avatar
qinsoon committed
89 90
        MuType_::Float => BackendTypeInfo{size: 4, alignment: 4, struct_layout: None},
        MuType_::Double => BackendTypeInfo{size: 8, alignment: 8, struct_layout: None},
qinsoon's avatar
qinsoon committed
91
        // array
qinsoon's avatar
qinsoon committed
92
        MuType_::Array(ref ty, len) => {
93
            let ele_ty = vm.get_backend_type_info(ty.id());
qinsoon's avatar
qinsoon committed
94 95 96 97
            
            BackendTypeInfo{size: ele_ty.size * len, alignment: ele_ty.alignment, struct_layout: None}
        }
        // struct
98
        MuType_::Struct(ref name) => {
qinsoon's avatar
qinsoon committed
99 100 101 102 103 104 105 106 107 108 109
            let read_lock = STRUCT_TAG_MAP.read().unwrap();
            let struc = read_lock.get(name).unwrap();
            let tys = struc.get_tys();            
            
            trace!("layout struct: {}", struc);
            layout_struct(tys, vm)
        }
        // hybrid 
        // - align is the most strict aligned element (from all fix tys and var ty)
        // - size is fixed tys size
        // - layout is fixed tys layout
110 111 112 113 114 115 116
        MuType_::Hybrid(ref name) => {
            let read_lock = HYBRID_TAG_MAP.read().unwrap();
            let hybrid = read_lock.get(name).unwrap();

            let fix_tys = hybrid.get_fix_tys();
            let var_ty  = hybrid.get_var_ty();

qinsoon's avatar
qinsoon committed
117 118 119 120
            // treat fix_tys as struct
            let mut ret = layout_struct(fix_tys, vm);
            
            // treat var_ty as array (getting its alignment)
121
            let var_align = vm.get_backend_type_info(var_ty.id()).alignment;
qinsoon's avatar
qinsoon committed
122 123 124 125 126 127 128 129
            
            if ret.alignment < var_align {
                ret.alignment = var_align;
            }
            
            ret
        }
        // void
qinsoon's avatar
qinsoon committed
130
        MuType_::Void => BackendTypeInfo{size: 0, alignment: 8, struct_layout: None},
qinsoon's avatar
qinsoon committed
131
        // vector
qinsoon's avatar
qinsoon committed
132
        MuType_::Vector(_, _) => unimplemented!()
qinsoon's avatar
qinsoon committed
133 134 135
    }
}

qinsoon's avatar
qinsoon committed
136
fn layout_struct(tys: &Vec<P<MuType>>, vm: &VM) -> BackendTypeInfo {
qinsoon's avatar
qinsoon committed
137 138
    let mut offsets : Vec<ByteSize> = vec![];
    let mut cur : ByteSize = 0;
qinsoon's avatar
qinsoon committed
139
    let mut struct_align : ByteSize = 1;
qinsoon's avatar
qinsoon committed
140 141
    
    for ty in tys.iter() {
142
        let ty_info = vm.get_backend_type_info(ty.id());
qinsoon's avatar
qinsoon committed
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
        trace!("examining field: {}, {:?}", ty, ty_info);
        
        let align = ty_info.alignment;
        if struct_align < align {
            struct_align = align;
        }
        
        if cur % align != 0 {
            // move cursor to next aligned offset
            cur = (cur / align + 1) * align;
        }
        
        offsets.push(cur);
        trace!("aligned to {}", cur);
        
        cur += ty_info.size;
    }
    
    // if we need padding at the end
    if cur % struct_align != 0 {
        cur = (cur / struct_align + 1) * struct_align;
    }
    
    BackendTypeInfo {
        size: cur,
        alignment: struct_align,
        struct_layout: Some(offsets)
    }
}

173 174 175 176 177 178
pub fn sequetial_layout(tys: &Vec<P<MuType>>, vm: &VM) -> (ByteSize, ByteSize, Vec<ByteSize>) {
    let ret = layout_struct(tys, vm);
    
    (ret.size, ret.alignment, ret.struct_layout.unwrap())
} 

qinsoon's avatar
qinsoon committed
179
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
180
pub struct BackendTypeInfo {
qinsoon's avatar
qinsoon committed
181 182 183
    pub size: ByteSize,
    pub alignment: ByteSize,
    pub struct_layout: Option<Vec<ByteSize>>
qinsoon's avatar
qinsoon committed
184 185
}

qinsoon's avatar
qinsoon committed
186
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
187
pub enum RegGroup {GPR, FPR}
188 189 190 191

impl RegGroup {
    pub fn get(ty: &P<MuType>) -> RegGroup {
        match ty.v {
qinsoon's avatar
qinsoon committed
192
            // for now, only use 64bits registers
193
            MuType_::Int(len) if len == 1  => RegGroup::GPR,
194 195 196 197
            MuType_::Int(len) if len == 8  => RegGroup::GPR,
            MuType_::Int(len) if len == 16 => RegGroup::GPR,
            MuType_::Int(len) if len == 32 => RegGroup::GPR,
            MuType_::Int(len) if len == 64 => RegGroup::GPR,
198 199 200 201 202 203 204 205 206

            MuType_::Ref(_)
            | MuType_::IRef(_)
            | MuType_::WeakRef(_)
            | MuType_::UPtr(_)
            | MuType_::ThreadRef
            | MuType_::StackRef
            | MuType_::Tagref64
            | MuType_::FuncRef(_)
207
            | MuType_::UFuncPtr(_)         => RegGroup::GPR,
208

209 210
            MuType_::Float                 => RegGroup::FPR,
            MuType_::Double                => RegGroup::FPR,
211 212 213 214 215

            _ => unimplemented!()
        }
    }
}