Commit d40c6303 authored by qinsoon's avatar qinsoon

global seems working fine

parent f192c70c
......@@ -8,7 +8,7 @@ use std::sync::RwLock;
pub type MuType = MuType_;
#[derive(Clone, PartialEq, Eq, Debug)]
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum MuType_ {
/// int <length>
Int (usize),
......@@ -110,6 +110,10 @@ impl StructType_ {
self.tys.clear();
self.tys.append(&mut list);
}
pub fn get_tys(&self) -> &Vec<P<MuType_>> {
&self.tys
}
}
impl MuType_ {
......@@ -303,7 +307,7 @@ macro_rules! is_type (
)
);
#[derive(Clone, PartialEq, Eq, Debug)]
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct MuFuncSig {
pub ret_tys : Vec<P<MuType>>,
pub arg_tys: Vec<P<MuType>>
......
#![allow(unused_variables)]
use compiler::backend;
use compiler::backend::ByteSize;
use compiler::backend::x86_64;
use compiler::backend::x86_64::CodeGenerator;
use vm::machine_code::MachineCode;
......@@ -470,7 +471,7 @@ impl ASMCodeGen {
loc_cursor += 1;
},
Value_::Memory(MemoryLocation::Symbolic{ref base, label}) => {
result_str.push_str(label);
result_str.push_str(&symbol(label));
loc_cursor += label.len();
if base.is_some() {
......@@ -505,7 +506,7 @@ impl ASMCodeGen {
}
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) {
......@@ -600,10 +601,8 @@ impl CodeGenerator for ASMCodeGen {
}));
// to link with C sources via gcc
self.add_asm_symbolic(format!(".globl {}", func_name));
self.add_asm_symbolic(format!(".globl _{}", func_name));
self.add_asm_symbolic(format!("{}:", func_name));
self.add_asm_symbolic(format!("_{}:", func_name));
self.add_asm_symbolic(directive_globl(symbol(func_name)));
self.add_asm_symbolic(format!("{}:", symbol(func_name)));
}
fn finish_code(&mut self) -> Box<MachineCode> {
......@@ -1002,7 +1001,7 @@ impl CodeGenerator for ASMCodeGen {
fn emit_call_near_rel32(&mut self, func: MuTag) {
trace!("emit: call {}", func);
let asm = format!("call {}", func);
let asm = format!("call {}", symbol(func));
self.add_asm_call(asm);
// FIXME: call interferes with machine registers
......@@ -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) {
use std::io::prelude::*;
use std::fs::File;
use std::fs;
use std::path;
let compiled_funcs = vm.compiled_funcs().read().unwrap();
let cf = compiled_funcs.get(func.fn_name).unwrap().borrow();
let code = cf.mc.emit();
const EMIT_DIR : &'static str = "emit";
match fs::create_dir(EMIT_DIR) {
Ok(_) => {},
Err(_) => {}
}
// create 'emit' directory
create_emit_directory();
let file_name = EMIT_DIR.to_string() + "/" + func.fn_name + ".s";
let mut file = match File::create(file_name.clone()) {
Err(why) => panic!("couldn't create emission file {}: {}", file_name, why),
let mut file_path = path::PathBuf::new();
file_path.push(EMIT_DIR);
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
};
match file.write_all(code.as_slice()) {
Err(why) => panic!("couldn'd write to file {}: {}", file_name, why),
Ok(_) => println!("emit code to {}", file_name)
Err(why) => panic!("couldn'd write to file {}: {}", file_path.to_str().unwrap(), why),
Ok(_) => println!("emit code to {}", file_path.to_str().unwrap())
}
}
const CONTEXT_FILE : &'static str = "context.s";
pub fn emit_context(vm: &VMContext) {
use std::path;
use std::fs::File;
use std::io::prelude::*;
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---");
}
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;
pub mod peephole_opt;
pub mod code_emission;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum RegGroup {GPR, FPR}
pub type ByteSize = usize;
// X86_64
#[cfg(target_arch = "x86_64")]
#[path = "arch/x86_64/mod.rs"]
......@@ -30,6 +31,124 @@ pub use compiler::backend::x86_64::emit_code;
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::emit_context;
// ARM
#[cfg(target_arch = "arm")]
#[path = "arch/arm/mod.rs"]
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;
use ast::ptr::P;
use ast::ir::*;
use ast::types::*;
use compiler::backend;
use compiler::backend::BackendTypeInfo;
use vm::machine_code::CompiledFunction;
use std::sync::RwLock;
......@@ -10,10 +12,12 @@ use std::cell::RefCell;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
pub struct VMContext {
pub is_running: AtomicBool,
is_running: AtomicBool,
constants: RwLock<HashMap<MuTag, P<Value>>>,
types: RwLock<HashMap<MuTag, P<MuType>>>,
backend_type_info: RwLock<HashMap<P<MuType>, BackendTypeInfo>>,
globals: RwLock<HashMap<MuTag, P<GlobalCell>>>,
......@@ -30,7 +34,9 @@ impl <'a> VMContext {
is_running: ATOMIC_BOOL_INIT,
constants: RwLock::new(HashMap::new()),
types: RwLock::new(HashMap::new()),
backend_type_info: RwLock::new(HashMap::new()),
globals: RwLock::new(HashMap::new()),
......@@ -135,6 +141,28 @@ impl <'a> VMContext {
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>>> {
&self.funcs
}
......
......@@ -69,16 +69,7 @@ fn test_regalloc_fac() {
let vm_context = Arc::new(factorial());
let compiler = Compiler::new(CompilerPolicy::new(vec![
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 compiler = Compiler::new(CompilerPolicy::default(), vm_context.clone());
let funcs = vm_context.funcs().read().unwrap();
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