Commit d40c6303 authored by qinsoon's avatar qinsoon

global seems working fine

parent f192c70c
...@@ -8,7 +8,7 @@ use std::sync::RwLock; ...@@ -8,7 +8,7 @@ use std::sync::RwLock;
pub type MuType = MuType_; pub type MuType = MuType_;
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum MuType_ { pub enum MuType_ {
/// int <length> /// int <length>
Int (usize), Int (usize),
...@@ -110,6 +110,10 @@ impl StructType_ { ...@@ -110,6 +110,10 @@ impl StructType_ {
self.tys.clear(); self.tys.clear();
self.tys.append(&mut list); self.tys.append(&mut list);
} }
pub fn get_tys(&self) -> &Vec<P<MuType_>> {
&self.tys
}
} }
impl MuType_ { impl MuType_ {
...@@ -303,7 +307,7 @@ macro_rules! is_type ( ...@@ -303,7 +307,7 @@ macro_rules! is_type (
) )
); );
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct MuFuncSig { pub struct MuFuncSig {
pub ret_tys : Vec<P<MuType>>, pub ret_tys : Vec<P<MuType>>,
pub arg_tys: Vec<P<MuType>> pub arg_tys: Vec<P<MuType>>
......
#![allow(unused_variables)] #![allow(unused_variables)]
use compiler::backend; use compiler::backend;
use compiler::backend::ByteSize;
use compiler::backend::x86_64; use compiler::backend::x86_64;
use compiler::backend::x86_64::CodeGenerator; use compiler::backend::x86_64::CodeGenerator;
use vm::machine_code::MachineCode; use vm::machine_code::MachineCode;
...@@ -470,7 +471,7 @@ impl ASMCodeGen { ...@@ -470,7 +471,7 @@ impl ASMCodeGen {
loc_cursor += 1; loc_cursor += 1;
}, },
Value_::Memory(MemoryLocation::Symbolic{ref base, label}) => { Value_::Memory(MemoryLocation::Symbolic{ref base, label}) => {
result_str.push_str(label); result_str.push_str(&symbol(label));
loc_cursor += label.len(); loc_cursor += label.len();
if base.is_some() { if base.is_some() {
...@@ -505,7 +506,7 @@ impl ASMCodeGen { ...@@ -505,7 +506,7 @@ impl ASMCodeGen {
} }
fn asm_block_label(&self, label: MuTag) -> String { fn asm_block_label(&self, label: MuTag) -> String {
format!("{}_{}", self.cur().name, label) symbol(&format!("{}_{}", self.cur().name, label))
} }
fn control_flow_analysis(&mut self) { fn control_flow_analysis(&mut self) {
...@@ -600,10 +601,8 @@ impl CodeGenerator for ASMCodeGen { ...@@ -600,10 +601,8 @@ impl CodeGenerator for ASMCodeGen {
})); }));
// to link with C sources via gcc // to link with C sources via gcc
self.add_asm_symbolic(format!(".globl {}", func_name)); self.add_asm_symbolic(directive_globl(symbol(func_name)));
self.add_asm_symbolic(format!(".globl _{}", func_name)); self.add_asm_symbolic(format!("{}:", symbol(func_name)));
self.add_asm_symbolic(format!("{}:", func_name));
self.add_asm_symbolic(format!("_{}:", func_name));
} }
fn finish_code(&mut self) -> Box<MachineCode> { fn finish_code(&mut self) -> Box<MachineCode> {
...@@ -1002,7 +1001,7 @@ impl CodeGenerator for ASMCodeGen { ...@@ -1002,7 +1001,7 @@ impl CodeGenerator for ASMCodeGen {
fn emit_call_near_rel32(&mut self, func: MuTag) { fn emit_call_near_rel32(&mut self, func: MuTag) {
trace!("emit: call {}", func); trace!("emit: call {}", func);
let asm = format!("call {}", func); let asm = format!("call {}", symbol(func));
self.add_asm_call(asm); self.add_asm_call(asm);
// FIXME: call interferes with machine registers // FIXME: call interferes with machine registers
...@@ -1062,36 +1061,93 @@ impl CodeGenerator for ASMCodeGen { ...@@ -1062,36 +1061,93 @@ impl CodeGenerator for ASMCodeGen {
} }
} }
const EMIT_DIR : &'static str = "emit";
fn create_emit_directory() {
use std::fs;
match fs::create_dir(EMIT_DIR) {
Ok(_) => {},
Err(_) => {}
}
}
pub fn emit_code(func: &mut MuFunctionVersion, vm: &VMContext) { pub fn emit_code(func: &mut MuFunctionVersion, vm: &VMContext) {
use std::io::prelude::*; use std::io::prelude::*;
use std::fs::File; use std::fs::File;
use std::fs; use std::path;
let compiled_funcs = vm.compiled_funcs().read().unwrap(); let compiled_funcs = vm.compiled_funcs().read().unwrap();
let cf = compiled_funcs.get(func.fn_name).unwrap().borrow(); let cf = compiled_funcs.get(func.fn_name).unwrap().borrow();
let code = cf.mc.emit(); let code = cf.mc.emit();
const EMIT_DIR : &'static str = "emit"; // create 'emit' directory
match fs::create_dir(EMIT_DIR) { create_emit_directory();
Ok(_) => {},
Err(_) => {}
}
let file_name = EMIT_DIR.to_string() + "/" + func.fn_name + ".s"; let mut file_path = path::PathBuf::new();
let mut file = match File::create(file_name.clone()) { file_path.push(EMIT_DIR);
Err(why) => panic!("couldn't create emission file {}: {}", file_name, why), file_path.push(func.fn_name.to_string() + ".s");
let mut file = match File::create(file_path.as_path()) {
Err(why) => panic!("couldn't create emission file {}: {}", file_path.to_str().unwrap(), why),
Ok(file) => file Ok(file) => file
}; };
match file.write_all(code.as_slice()) { match file.write_all(code.as_slice()) {
Err(why) => panic!("couldn'd write to file {}: {}", file_name, why), Err(why) => panic!("couldn'd write to file {}: {}", file_path.to_str().unwrap(), why),
Ok(_) => println!("emit code to {}", file_name) Ok(_) => println!("emit code to {}", file_path.to_str().unwrap())
} }
} }
const CONTEXT_FILE : &'static str = "context.s";
pub fn emit_context(vm: &VMContext) { pub fn emit_context(vm: &VMContext) {
use std::path;
use std::fs::File;
use std::io::prelude::*;
debug!("---Emit VM Context---"); debug!("---Emit VM Context---");
create_emit_directory();
let mut file_path = path::PathBuf::new();
file_path.push(EMIT_DIR);
file_path.push(CONTEXT_FILE);
let mut file = match File::create(file_path.as_path()) {
Err(why) => panic!("couldn't create context file {}: {}", file_path.to_str().unwrap(), why),
Ok(file) => file
};
// put globals into bss section
file.write_fmt(format_args!("\t.bss\n")).unwrap();
let globals = vm.globals().read().unwrap();
for cell in globals.values() {
let (size, align) = {
let ty_info = vm.get_backend_type_info(&cell.ty);
(ty_info.size, ty_info.alignment)
};
file.write_fmt(format_args!("\t{}\n", directive_globl(symbol(cell.tag)))).unwrap();
file.write_fmt(format_args!("\t{}\n", directive_comm(symbol(cell.tag), size, align))).unwrap();
file.write("\n".as_bytes()).unwrap();
}
debug!("---finish---"); debug!("---finish---");
}
fn directive_globl(name: String) -> String {
format!(".globl {}", name)
}
fn directive_comm(name: String, size: ByteSize, align: ByteSize) -> String {
format!(".comm {},{},{}", name, size, align)
}
#[cfg(target_os = "linux")]
fn symbol(name: &str) -> String {
name.to_string()
}
#[cfg(target_os = "macos")]
fn symbol(name: &str) -> String {
format!("_{}", name)
} }
\ No newline at end of file
...@@ -3,8 +3,9 @@ pub mod reg_alloc; ...@@ -3,8 +3,9 @@ pub mod reg_alloc;
pub mod peephole_opt; pub mod peephole_opt;
pub mod code_emission; pub mod code_emission;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub type ByteSize = usize;
pub enum RegGroup {GPR, FPR}
// X86_64
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
#[path = "arch/x86_64/mod.rs"] #[path = "arch/x86_64/mod.rs"]
...@@ -30,6 +31,124 @@ pub use compiler::backend::x86_64::emit_code; ...@@ -30,6 +31,124 @@ pub use compiler::backend::x86_64::emit_code;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::emit_context; pub use compiler::backend::x86_64::emit_context;
// ARM
#[cfg(target_arch = "arm")] #[cfg(target_arch = "arm")]
#[path = "arch/arm/mod.rs"] #[path = "arch/arm/mod.rs"]
mod arm; mod arm;
// common data structure with target specific info
use vm::context::VMContext;
use ast::types::*;
use ast::ptr::*;
pub fn resolve_backend_type_info (ty: &MuType, vm: &VMContext) -> BackendTypeInfo {
match ty {
// integral
&MuType_::Int(size_in_bit) => {
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
&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},
// floating point
&MuType_::Float => BackendTypeInfo{size: 4, alignment: 4, struct_layout: None},
&MuType_::Double => BackendTypeInfo{size: 8, alignment: 8, struct_layout: None},
// array
&MuType_::Array(ref ty, len) => {
let ele_ty = vm.get_backend_type_info(ty);
BackendTypeInfo{size: ele_ty.size * len, alignment: ele_ty.alignment, struct_layout: None}
}
// struct
&MuType_::Struct(name) => {
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
&MuType_::Hybrid(ref fix_tys, ref var_ty) => {
// treat fix_tys as struct
let mut ret = layout_struct(fix_tys, vm);
// treat var_ty as array (getting its alignment)
let var_align = vm.get_backend_type_info(var_ty).alignment;
if ret.alignment < var_align {
ret.alignment = var_align;
}
ret
}
// void
&MuType_::Void => BackendTypeInfo{size: 0, alignment: 8, struct_layout: None},
// vector
&MuType_::Vector(_, _) => unimplemented!()
}
}
fn layout_struct(tys: &Vec<P<MuType_>>, vm: &VMContext) -> BackendTypeInfo {
let mut offsets : Vec<ByteSize> = vec![];
let mut cur : ByteSize = 0;
let mut struct_align : ByteSize = 0;
for ty in tys.iter() {
let ty_info = vm.get_backend_type_info(ty);
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)
}
}
#[derive(Clone, Debug)]
pub struct BackendTypeInfo {
size: ByteSize,
alignment: ByteSize,
struct_layout: Option<Vec<ByteSize>>
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum RegGroup {GPR, FPR}
\ No newline at end of file
...@@ -3,6 +3,8 @@ use std::collections::HashMap; ...@@ -3,6 +3,8 @@ use std::collections::HashMap;
use ast::ptr::P; use ast::ptr::P;
use ast::ir::*; use ast::ir::*;
use ast::types::*; use ast::types::*;
use compiler::backend;
use compiler::backend::BackendTypeInfo;
use vm::machine_code::CompiledFunction; use vm::machine_code::CompiledFunction;
use std::sync::RwLock; use std::sync::RwLock;
...@@ -10,10 +12,12 @@ use std::cell::RefCell; ...@@ -10,10 +12,12 @@ use std::cell::RefCell;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
pub struct VMContext { pub struct VMContext {
pub is_running: AtomicBool, is_running: AtomicBool,
constants: RwLock<HashMap<MuTag, P<Value>>>, constants: RwLock<HashMap<MuTag, P<Value>>>,
types: RwLock<HashMap<MuTag, P<MuType>>>, types: RwLock<HashMap<MuTag, P<MuType>>>,
backend_type_info: RwLock<HashMap<P<MuType>, BackendTypeInfo>>,
globals: RwLock<HashMap<MuTag, P<GlobalCell>>>, globals: RwLock<HashMap<MuTag, P<GlobalCell>>>,
...@@ -30,7 +34,9 @@ impl <'a> VMContext { ...@@ -30,7 +34,9 @@ impl <'a> VMContext {
is_running: ATOMIC_BOOL_INIT, is_running: ATOMIC_BOOL_INIT,
constants: RwLock::new(HashMap::new()), constants: RwLock::new(HashMap::new()),
types: RwLock::new(HashMap::new()), types: RwLock::new(HashMap::new()),
backend_type_info: RwLock::new(HashMap::new()),
globals: RwLock::new(HashMap::new()), globals: RwLock::new(HashMap::new()),
...@@ -135,6 +141,28 @@ impl <'a> VMContext { ...@@ -135,6 +141,28 @@ impl <'a> VMContext {
self.compiled_funcs.write().unwrap().insert(func.fn_name, RefCell::new(func)); self.compiled_funcs.write().unwrap().insert(func.fn_name, RefCell::new(func));
} }
pub fn get_backend_type_info(&self, ty: &P<MuType>) -> BackendTypeInfo {
{
let read_lock = self.backend_type_info.read().unwrap();
match read_lock.get(ty) {
Some(info) => {return info.clone();},
None => {}
}
}
let resolved = backend::resolve_backend_type_info(ty, self);
let mut write_lock = self.backend_type_info.write().unwrap();
write_lock.insert(ty.clone(), resolved.clone());
resolved
}
pub fn globals(&self) -> &RwLock<HashMap<MuTag, P<GlobalCell>>> {
&self.globals
}
pub fn funcs(&self) -> &RwLock<HashMap<MuTag, RefCell<MuFunction>>> { pub fn funcs(&self) -> &RwLock<HashMap<MuTag, RefCell<MuFunction>>> {
&self.funcs &self.funcs
} }
......
...@@ -69,16 +69,7 @@ fn test_regalloc_fac() { ...@@ -69,16 +69,7 @@ fn test_regalloc_fac() {
let vm_context = Arc::new(factorial()); let vm_context = Arc::new(factorial());
let compiler = Compiler::new(CompilerPolicy::new(vec![ let compiler = Compiler::new(CompilerPolicy::default(), vm_context.clone());
Box::new(passes::DefUse::new()),
Box::new(passes::TreeGen::new()),
Box::new(passes::ControlFlowAnalysis::new()),
Box::new(passes::TraceGen::new()),
Box::new(backend::inst_sel::InstructionSelection::new()),
Box::new(backend::reg_alloc::RegisterAllocation::new()),
Box::new(backend::peephole_opt::PeepholeOptimization::new()),
Box::new(backend::code_emission::CodeEmission::new())
]), vm_context.clone());
let funcs = vm_context.funcs().read().unwrap(); let funcs = vm_context.funcs().read().unwrap();
let factorial_func = funcs.get("fac").unwrap().borrow(); let factorial_func = funcs.get("fac").unwrap().borrow();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment