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

6
use ast::types;
qinsoon's avatar
qinsoon committed
7
use utils::ByteSize;
8 9
use runtime::mm;
use runtime::mm::common::gctype::{GCType, GCTYPE_INIT_ID, RefPattern, RepeatingRefPattern};
qinsoon's avatar
qinsoon committed
10

11 12 13
pub type Word = usize;
pub const WORD_SIZE : ByteSize = 8;

14 15
pub const AOT_EMIT_CONTEXT_FILE : &'static str = "context.s";

qinsoon's avatar
qinsoon committed
16 17 18 19
// 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
20 21 22
pub type Reg<'a> = &'a P<Value>;
pub type Mem<'a> = &'a P<Value>;

qinsoon's avatar
qinsoon committed
23
// X86_64
qinsoon's avatar
qinsoon committed
24

25
#[cfg(target_arch = "x86_64")]
26
#[path = "arch/x86_64/mod.rs"]
27
pub mod x86_64;
28

29 30
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::estimate_insts_for_ir;
qinsoon's avatar
qinsoon committed
31
#[cfg(target_arch = "x86_64")]
qinsoon's avatar
qinsoon committed
32
pub use compiler::backend::x86_64::init_machine_regs_for_func;
33 34
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::is_aliased;
qinsoon's avatar
qinsoon committed
35
#[cfg(target_arch = "x86_64")]
qinsoon's avatar
qinsoon committed
36
pub use compiler::backend::x86_64::get_color_for_precolored;
qinsoon's avatar
qinsoon committed
37
#[cfg(target_arch = "x86_64")]
qinsoon's avatar
qinsoon committed
38
pub use compiler::backend::x86_64::number_of_regs_in_group;
qinsoon's avatar
qinsoon committed
39
#[cfg(target_arch = "x86_64")]
qinsoon's avatar
qinsoon committed
40 41 42
pub use compiler::backend::x86_64::number_of_all_regs;
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::all_regs;
43
#[cfg(target_arch = "x86_64")]
44 45
pub use compiler::backend::x86_64::all_usable_regs;
#[cfg(target_arch = "x86_64")]
46
pub use compiler::backend::x86_64::pick_group_for_reg;
47 48
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::is_callee_saved;
49 50 51 52
#[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;
53 54
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::spill_rewrite;
qinsoon's avatar
qinsoon committed
55

qinsoon's avatar
qinsoon committed
56 57
// ARM

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

// common data structure with target specific info

qinsoon's avatar
qinsoon committed
64
use vm::VM;
qinsoon's avatar
qinsoon committed
65 66
use ast::types::*;
use ast::ptr::*;
67
use ast::ir::*;
qinsoon's avatar
qinsoon committed
68
pub fn resolve_backend_type_info (ty: &MuType, vm: &VM) -> BackendTypeInfo {
qinsoon's avatar
qinsoon committed
69
    match ty.v {
70
        // integer
qinsoon's avatar
qinsoon committed
71
        MuType_::Int(size_in_bit) => {
qinsoon's avatar
qinsoon committed
72
            match size_in_bit {
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
                1  => BackendTypeInfo{
                    size: 1, alignment: 1, struct_layout: None,
                    gc_type: mm::add_gc_type(GCType::new_noreftype(1))
                },
                8  => BackendTypeInfo{
                    size: 1, alignment: 1, struct_layout: None,
                    gc_type: mm::add_gc_type(GCType::new_noreftype(1))
                },
                16 => BackendTypeInfo{
                    size: 2, alignment: 2, struct_layout: None,
                    gc_type: mm::add_gc_type(GCType::new_noreftype(2))
                },
                32 => BackendTypeInfo{
                    size: 4, alignment: 4, struct_layout: None,
                    gc_type: mm::add_gc_type(GCType::new_noreftype(4))
                },
                64 => BackendTypeInfo{
                    size: 8, alignment: 8, struct_layout: None,
                    gc_type: mm::add_gc_type(GCType::new_noreftype(8))
                },
qinsoon's avatar
qinsoon committed
93 94 95
                _ => unimplemented!()
            }
        },
96
        // reference of any type
qinsoon's avatar
qinsoon committed
97 98
        MuType_::Ref(_)
        | MuType_::IRef(_)
99 100 101 102 103 104
        | MuType_::WeakRef(_) => BackendTypeInfo{
            size: 8, alignment: 8, struct_layout: None,
            gc_type: mm::add_gc_type(GCType::new_reftype())
        },
        // pointer
        MuType_::UPtr(_)
qinsoon's avatar
qinsoon committed
105
        | MuType_::UFuncPtr(_)
106
        | MuType_::FuncRef(_)
qinsoon's avatar
qinsoon committed
107
        | MuType_::ThreadRef
108 109 110 111 112 113
        | MuType_::StackRef => BackendTypeInfo{
            size: 8, alignment: 8, struct_layout: None,
            gc_type: mm::add_gc_type(GCType::new_noreftype(8))
        },
        // tagref
        MuType_::Tagref64 => unimplemented!(),
qinsoon's avatar
qinsoon committed
114
        // floating point
115 116 117 118 119 120 121 122
        MuType_::Float => BackendTypeInfo{
            size: 4, alignment: 4, struct_layout: None,
            gc_type: mm::add_gc_type(GCType::new_noreftype(4))
        },
        MuType_::Double => BackendTypeInfo {
            size: 8, alignment: 8, struct_layout: None,
            gc_type: mm::add_gc_type(GCType::new_noreftype(8))
        },
qinsoon's avatar
qinsoon committed
123
        // array
qinsoon's avatar
qinsoon committed
124
        MuType_::Array(ref ty, len) => {
125
            let ele_ty = vm.get_backend_type_info(ty.id());
qinsoon's avatar
qinsoon committed
126
            
127 128 129 130 131 132 133 134 135 136 137 138 139 140
            BackendTypeInfo{
                size         : ele_ty.size * len,
                alignment    : ele_ty.alignment,
                struct_layout: None,
                gc_type      : mm::add_gc_type(GCType {
                    id             : GCTYPE_INIT_ID,
                    size           : ele_ty.size * len,
                    non_repeat_refs: None,
                    repeat_refs    : Some(RepeatingRefPattern{
                        pattern: RefPattern::NestedType(vec![ele_ty.gc_type]),
                        count  : len
                    })
                })
            }
qinsoon's avatar
qinsoon committed
141 142
        }
        // struct
143
        MuType_::Struct(ref name) => {
qinsoon's avatar
qinsoon committed
144 145 146 147 148 149 150 151 152 153 154
            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
155 156 157 158 159 160 161
        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
162 163 164 165
            // treat fix_tys as struct
            let mut ret = layout_struct(fix_tys, vm);
            
            // treat var_ty as array (getting its alignment)
166 167 168 169 170
            let var_ele_ty = vm.get_backend_type_info(var_ty.id());
            let var_align = var_ele_ty.alignment;

            // fix type info as hybrid
            // 1. check alignment
qinsoon's avatar
qinsoon committed
171 172 173
            if ret.alignment < var_align {
                ret.alignment = var_align;
            }
174 175 176 177 178 179 180
            // 2. fix gc type
            let mut gctype = ret.gc_type.as_ref().clone();
            gctype.repeat_refs = Some(RepeatingRefPattern {
                pattern: RefPattern::NestedType(vec![var_ele_ty.gc_type.clone()]),
                count  : 0
            });
            ret.gc_type = mm::add_gc_type(gctype);
qinsoon's avatar
qinsoon committed
181 182 183 184
            
            ret
        }
        // void
185 186 187 188
        MuType_::Void => BackendTypeInfo{
            size: 0, alignment: 8, struct_layout: None,
            gc_type: mm::add_gc_type(GCType::new_noreftype(0))
        },
qinsoon's avatar
qinsoon committed
189
        // vector
qinsoon's avatar
qinsoon committed
190
        MuType_::Vector(_, _) => unimplemented!()
qinsoon's avatar
qinsoon committed
191 192 193
    }
}

qinsoon's avatar
qinsoon committed
194
fn layout_struct(tys: &Vec<P<MuType>>, vm: &VM) -> BackendTypeInfo {
qinsoon's avatar
qinsoon committed
195 196
    let mut offsets : Vec<ByteSize> = vec![];
    let mut cur : ByteSize = 0;
qinsoon's avatar
qinsoon committed
197
    let mut struct_align : ByteSize = 1;
198 199 200 201 202

    // for gc type
    let mut use_ref_offsets = true;
    let mut ref_offsets = vec![];
    let mut gc_types    = vec![];
qinsoon's avatar
qinsoon committed
203 204
    
    for ty in tys.iter() {
205
        let ty_info = vm.get_backend_type_info(ty.id());
qinsoon's avatar
qinsoon committed
206 207 208 209 210 211 212 213 214 215 216 217 218 219
        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);
220 221 222 223 224 225 226 227 228 229 230 231 232 233

        // for convenience, if the struct contains other struct/array
        // we do not use reference map
        if types::is_aggregate(ty) {
            use_ref_offsets = false;
        }

        // if this type is reference type, we store its offsets
        // we may not use this ref map though
        if types::is_reference(ty) {
            ref_offsets.push(cur);
        }
        // always store its gc type (we may not use it as well)
        gc_types.push(ty_info.gc_type.clone());
qinsoon's avatar
qinsoon committed
234 235 236 237 238
        
        cur += ty_info.size;
    }
    
    // if we need padding at the end
239 240 241 242 243
    let size = if cur % struct_align != 0 {
        (cur / struct_align + 1) * struct_align
    } else {
        cur
    };
qinsoon's avatar
qinsoon committed
244 245
    
    BackendTypeInfo {
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
        size         : size,
        alignment    : struct_align,
        struct_layout: Some(offsets),
        gc_type      : mm::add_gc_type(GCType {
            id             : GCTYPE_INIT_ID,
            size           : size,
            non_repeat_refs: Some(if use_ref_offsets {
                RefPattern::Map {
                    offsets: ref_offsets,
                    size: size
                }
            } else {
                RefPattern::NestedType(gc_types)
            }),
            repeat_refs    : None
        })
qinsoon's avatar
qinsoon committed
262 263 264
    }
}

265 266 267 268 269 270
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
271
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
272
pub struct BackendTypeInfo {
qinsoon's avatar
qinsoon committed
273 274
    pub size: ByteSize,
    pub alignment: ByteSize,
275 276 277
    pub struct_layout: Option<Vec<ByteSize>>,

    pub gc_type: P<GCType>
qinsoon's avatar
qinsoon committed
278 279
}

qinsoon's avatar
qinsoon committed
280
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
281
pub enum RegGroup {GPR, FPR}
282 283 284 285

impl RegGroup {
    pub fn get(ty: &P<MuType>) -> RegGroup {
        match ty.v {
qinsoon's avatar
qinsoon committed
286
            // for now, only use 64bits registers
287
            MuType_::Int(len) if len == 1  => RegGroup::GPR,
288 289 290 291
            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,
292 293 294 295 296 297 298 299 300

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

303 304
            MuType_::Float                 => RegGroup::FPR,
            MuType_::Double                => RegGroup::FPR,
305 306 307 308

            _ => unimplemented!()
        }
    }
309
}