mod.rs 5.26 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 13
pub const AOT_EMIT_DIR : &'static str = "emit";
pub const AOT_EMIT_CONTEXT_FILE : &'static str = "context.s";

qinsoon's avatar
qinsoon committed
14
// X86_64
qinsoon's avatar
qinsoon committed
15

16
#[cfg(target_arch = "x86_64")]
17
#[path = "arch/x86_64/mod.rs"]
18
pub mod x86_64;
19

qinsoon's avatar
qinsoon committed
20
#[cfg(target_arch = "x86_64")]
qinsoon's avatar
qinsoon committed
21
pub use compiler::backend::x86_64::init_machine_regs_for_func;
qinsoon's avatar
qinsoon committed
22 23

#[cfg(target_arch = "x86_64")]
qinsoon's avatar
qinsoon committed
24
pub use compiler::backend::x86_64::number_of_regs_in_group;
qinsoon's avatar
qinsoon committed
25
#[cfg(target_arch = "x86_64")]
qinsoon's avatar
qinsoon committed
26 27 28
pub use compiler::backend::x86_64::number_of_all_regs;
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::all_regs;
29
#[cfg(target_arch = "x86_64")]
30 31
pub use compiler::backend::x86_64::all_usable_regs;
#[cfg(target_arch = "x86_64")]
32
pub use compiler::backend::x86_64::pick_group_for_reg;
33 34
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::is_callee_saved;
35 36 37 38
#[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;
39 40
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::spill_rewrite;
qinsoon's avatar
qinsoon committed
41

qinsoon's avatar
qinsoon committed
42 43
// ARM

qinsoon's avatar
qinsoon committed
44 45 46
#[cfg(target_arch = "arm")]
#[path = "arch/arm/mod.rs"]
mod arm;
qinsoon's avatar
qinsoon committed
47 48 49

// common data structure with target specific info

qinsoon's avatar
qinsoon committed
50
use vm::VM;
qinsoon's avatar
qinsoon committed
51 52
use ast::types::*;
use ast::ptr::*;
53
use ast::ir::*;
qinsoon's avatar
qinsoon committed
54
pub fn resolve_backend_type_info (ty: &MuType, vm: &VM) -> BackendTypeInfo {
qinsoon's avatar
qinsoon committed
55
    match ty.v {
qinsoon's avatar
qinsoon committed
56
        // integral
qinsoon's avatar
qinsoon committed
57
        MuType_::Int(size_in_bit) => {
qinsoon's avatar
qinsoon committed
58 59 60 61 62 63 64 65 66
            match size_in_bit {
                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
67 68 69 70 71 72 73 74 75
        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
76
        // floating point
qinsoon's avatar
qinsoon committed
77 78
        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
79
        // array
qinsoon's avatar
qinsoon committed
80
        MuType_::Array(ref ty, len) => {
81
            let ele_ty = vm.get_backend_type_info(ty.id());
qinsoon's avatar
qinsoon committed
82 83 84 85
            
            BackendTypeInfo{size: ele_ty.size * len, alignment: ele_ty.alignment, struct_layout: None}
        }
        // struct
86
        MuType_::Struct(ref name) => {
qinsoon's avatar
qinsoon committed
87 88 89 90 91 92 93 94 95 96 97
            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
qinsoon's avatar
qinsoon committed
98
        MuType_::Hybrid(ref fix_tys, ref var_ty) => {
qinsoon's avatar
qinsoon committed
99 100 101 102
            // treat fix_tys as struct
            let mut ret = layout_struct(fix_tys, vm);
            
            // treat var_ty as array (getting its alignment)
103
            let var_align = vm.get_backend_type_info(var_ty.id()).alignment;
qinsoon's avatar
qinsoon committed
104 105 106 107 108 109 110 111
            
            if ret.alignment < var_align {
                ret.alignment = var_align;
            }
            
            ret
        }
        // void
qinsoon's avatar
qinsoon committed
112
        MuType_::Void => BackendTypeInfo{size: 0, alignment: 8, struct_layout: None},
qinsoon's avatar
qinsoon committed
113
        // vector
qinsoon's avatar
qinsoon committed
114
        MuType_::Vector(_, _) => unimplemented!()
qinsoon's avatar
qinsoon committed
115 116 117
    }
}

qinsoon's avatar
qinsoon committed
118
fn layout_struct(tys: &Vec<P<MuType>>, vm: &VM) -> BackendTypeInfo {
qinsoon's avatar
qinsoon committed
119 120 121 122 123
    let mut offsets : Vec<ByteSize> = vec![];
    let mut cur : ByteSize = 0;
    let mut struct_align : ByteSize = 0;
    
    for ty in tys.iter() {
124
        let ty_info = vm.get_backend_type_info(ty.id());
qinsoon's avatar
qinsoon committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
        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)
    }
}

155 156 157 158 159 160
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
161
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
162
pub struct BackendTypeInfo {
qinsoon's avatar
qinsoon committed
163 164 165
    pub size: ByteSize,
    pub alignment: ByteSize,
    pub struct_layout: Option<Vec<ByteSize>>
qinsoon's avatar
qinsoon committed
166 167
}

qinsoon's avatar
qinsoon committed
168
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
169
pub enum RegGroup {GPR, FPR}