GitLab will be upgraded to the 12.10.14-ce.0 on 28 Sept 2020 at 2.00pm (AEDT) to 2.30pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

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