Commit 04c10e0b authored by qinsoon's avatar qinsoon

fixed all tests. Now using a lock for MuName

parent b20cc1a4
......@@ -8,6 +8,7 @@ use utils::vec_utils;
use std::collections::HashMap;
use std::fmt;
use std::default;
use std::sync::RwLock;
use std::cell::Cell;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
......@@ -55,8 +56,7 @@ pub fn new_internal_id() -> MuID {
#[derive(Debug)]
pub struct MuFunction {
pub id: MuID,
pub name: Option<MuName>,
pub hdr: MuEntityHeader,
pub sig: P<MuFuncSig>,
pub cur_ver: Option<MuID>,
......@@ -66,8 +66,7 @@ pub struct MuFunction {
impl MuFunction {
pub fn new(id: MuID, sig: P<MuFuncSig>) -> MuFunction {
MuFunction {
id: id,
name: None,
hdr: MuEntityHeader::unnamed(id),
sig: sig,
cur_ver: None,
all_vers: vec![]
......@@ -77,18 +76,13 @@ impl MuFunction {
impl fmt::Display for MuFunction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.name.is_none() {
write!(f, "Func #{}", self.id)
} else {
write!(f, "Func {}#{}", self.name.unwrap(), self.id)
}
write!(f, "Func {}", self.hdr)
}
}
#[derive(Debug)]
pub struct MuFunctionVersion {
pub id: MuID,
pub name: Option<MuName>,
pub hdr: MuEntityHeader,
pub func_id: MuID,
pub sig: P<MuFuncSig>,
......@@ -100,19 +94,14 @@ pub struct MuFunctionVersion {
impl fmt::Display for MuFunctionVersion {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.name.is_none() {
write!(f, "FuncVer #{} of Func#{}", self.id, self.func_id)
} else {
write!(f, "FuncVer {}#{} of Func#{}", self.name.unwrap(), self.id, self.func_id)
}
write!(f, "FuncVer {} of Func #{}", self.hdr, self.func_id)
}
}
impl MuFunctionVersion {
pub fn new(id: MuID, func: MuID, sig: P<MuFuncSig>) -> MuFunctionVersion {
MuFunctionVersion{
id: id,
name: None,
hdr: MuEntityHeader::unnamed(id),
func_id: func,
sig: sig,
content: None,
......@@ -129,12 +118,10 @@ impl MuFunctionVersion {
self.context.values.insert(id, SSAVarEntry{id: id, name: Some(tag), ty: ty.clone(), use_count: Cell::new(0), expr: None});
P(TreeNode {
id: id,
name: None,
hdr: MuEntityHeader::unnamed(id),
op: pick_op_code_for_ssa(&ty),
v: TreeNode_::Value(P(Value{
id: id,
name: Some(tag),
hdr: MuEntityHeader::named(id, tag),
ty: ty,
v: Value_::SSAVar(id)
}))
......@@ -143,8 +130,7 @@ impl MuFunctionVersion {
pub fn new_constant(&mut self, id: MuID, v: P<Value>) -> P<TreeNode> {
P(TreeNode{
id: id,
name: None,
hdr: MuEntityHeader::unnamed(id),
op: pick_op_code_for_value(&v.ty),
v: TreeNode_::Value(v)
})
......@@ -152,8 +138,7 @@ impl MuFunctionVersion {
pub fn new_global(&mut self, id: MuID, v: P<Value>) -> P<TreeNode> {
P(TreeNode{
id: id,
name: None,
hdr: MuEntityHeader::unnamed(id),
op: pick_op_code_for_value(&v.ty),
v: TreeNode_::Value(v)
})
......@@ -161,8 +146,7 @@ impl MuFunctionVersion {
pub fn new_inst(&mut self, id: MuID, v: Instruction) -> P<TreeNode> {
P(TreeNode{
id: id,
name: None,
hdr: MuEntityHeader::unnamed(id),
op: pick_op_code_for_inst(&v),
v: TreeNode_::Instruction(v),
})
......@@ -243,15 +227,14 @@ impl FunctionContext {
#[derive(Debug)]
pub struct Block {
pub id: MuID,
pub name: Option<MuName>,
pub hdr: MuEntityHeader,
pub content: Option<BlockContent>,
pub control_flow: ControlFlow
}
impl Block {
pub fn new(id: MuID) -> Block {
Block{id: id, name: None, content: None, control_flow: ControlFlow::default()}
Block{hdr: MuEntityHeader::unnamed(id), content: None, control_flow: ControlFlow::default()}
}
}
......@@ -391,11 +374,10 @@ impl BlockContent {
}
}
#[derive(Debug, Clone)]
#[derive(Debug)]
/// always use with P<TreeNode>
pub struct TreeNode {
pub id: MuID,
pub name: Option<MuName>,
pub hdr: MuEntityHeader,
pub op: OpCode,
pub v: TreeNode_,
}
......@@ -404,8 +386,7 @@ impl TreeNode {
// this is a hack to allow creating TreeNode without using a &mut MuFunctionVersion
pub fn new_inst(id: MuID, v: Instruction) -> P<TreeNode> {
P(TreeNode{
id: id,
name: None,
hdr: MuEntityHeader::unnamed(id),
op: pick_op_code_for_inst(&v),
v: TreeNode_::Instruction(v),
})
......@@ -464,10 +445,9 @@ pub enum TreeNode_ {
}
/// always use with P<Value>
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, PartialEq)]
pub struct Value {
pub id: MuID,
pub name: Option<MuName>,
pub hdr: MuEntityHeader,
pub ty: P<MuType>,
pub v: Value_
}
......@@ -522,25 +502,18 @@ impl Value {
impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let tag = {
if self.name.is_some() {
self.name.unwrap()
} else {
"???"
}
};
match self.v {
Value_::SSAVar(id) => {
write!(f, "+({} %{}#{})", self.ty, tag, id)
write!(f, "+({} %{})", self.ty, self.hdr)
},
Value_::Constant(ref c) => {
write!(f, "+({} {})", self.ty, c)
write!(f, "+({} {} @{})", self.ty, c, self.hdr)
},
Value_::Global => {
write!(f, "+(GLOBAL {} @{})", self.ty, self.name.unwrap())
Value_::Global(ref ty) => {
write!(f, "+(GLOBAL {} @{})", ty, self.hdr)
},
Value_::Memory(ref mem) => {
write!(f, "+({})", mem)
write!(f, "+(MEM {} %{})", mem, self.hdr)
}
}
}
......@@ -550,7 +523,7 @@ impl fmt::Display for Value {
pub enum Value_ {
SSAVar(MuID),
Constant(Constant),
Global,
Global(P<MuType>), // what type is this global (without IRef)
Memory(MemoryLocation)
}
......@@ -649,30 +622,74 @@ impl fmt::Display for MemoryLocation {
}
}
#[derive(Debug)] // Display, PartialEq
pub struct MuEntityHeader {
id: MuID,
name: RwLock<Option<MuName>>
}
impl MuEntityHeader {
pub fn unnamed(id: MuID) -> MuEntityHeader {
MuEntityHeader {
id: id,
name: RwLock::new(None)
}
}
pub fn named(id: MuID, name: MuName) -> MuEntityHeader {
MuEntityHeader {
id: id,
name: RwLock::new(Some(name))
}
}
pub fn id(&self) -> MuID {
self.id
}
pub fn name(&self) -> Option<MuName> {
*self.name.read().unwrap()
}
}
impl PartialEq for MuEntityHeader {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl fmt::Display for MuEntityHeader {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.name().is_none() {
write!(f, "#{}", self.id)
} else {
write!(f, "{} #{}", self.name().unwrap(), self.id)
}
}
}
pub trait MuEntity {
fn id(&self) -> MuID;
fn name(&self) -> Option<MuName>;
fn set_name(&mut self, name: MuName);
fn set_name(&self, name: MuName);
fn as_entity(&self) -> &MuEntity;
fn as_entity_mut(&mut self) -> &mut MuEntity;
}
macro_rules! impl_mu_entity {
($entity: ty) => {
impl MuEntity for $entity {
#[inline(always)]
fn id(&self) -> MuID {self.id}
fn id(&self) -> MuID {self.hdr.id}
#[inline(always)]
fn name(&self) -> Option<MuName> {self.name}
fn set_name(&mut self, name: MuName) {self.name = Some(name);}
fn name(&self) -> Option<MuName> {self.hdr.name()}
fn set_name(&self, name: MuName) {
let mut write_guard = self.hdr.name.write().unwrap();
*write_guard = Some(name);
}
fn as_entity(&self) -> &MuEntity {
let ref_ty : &$entity = self;
ref_ty as &MuEntity
}
fn as_entity_mut(&mut self) -> &mut MuEntity {
let ref_ty : &mut $entity = self;
ref_ty as &mut MuEntity
}
}
}
}
......
......@@ -41,76 +41,78 @@ use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::ops::DerefMut;
/// An owned smart pointer.
pub struct P<T> {
ptr: Box<T>
}
use std::sync::Arc;
pub type P<T> = Arc<T>;
///// An owned smart pointer.
//pub struct P<T> {
// ptr: Box<T>
//}
#[allow(non_snake_case)]
/// Construct a `P<T>` from a `T` value.
pub fn P<T: 'static>(value: T) -> P<T> {
P {
ptr: Box::new(value)
}
}
impl<T: 'static> P<T> {
/// Move out of the pointer.
/// Intended for chaining transformations not covered by `map`.
pub fn and_then<U, F>(self, f: F) -> U where
F: FnOnce(T) -> U,
{
f(*self.ptr)
}
}
impl<T> Deref for P<T> {
type Target = T;
fn deref<'a>(&'a self) -> &'a T {
&*self.ptr
}
}
impl<T> DerefMut for P<T> {
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
&mut *self.ptr
}
}
impl<T: 'static + Clone> Clone for P<T> {
fn clone(&self) -> P<T> {
P((**self).clone())
}
}
impl<T: PartialEq> PartialEq for P<T> {
fn eq(&self, other: &P<T>) -> bool {
**self == **other
}
}
impl<T: Eq> Eq for P<T> {}
impl<T: Debug> Debug for P<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&**self, f)
}
}
impl<T: Display> Display for P<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&**self, f)
}
}
impl<T> fmt::Pointer for P<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Pointer::fmt(&self.ptr, f)
}
Arc::new(value)
}
impl<T: Hash> Hash for P<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}
//impl<T: 'static> P<T> {
// /// Move out of the pointer.
// /// Intended for chaining transformations not covered by `map`.
// pub fn and_then<U, F>(self, f: F) -> U where
// F: FnOnce(T) -> U,
// {
// f(*self.ptr)
// }
//}
//
//impl<T> Deref for P<T> {
// type Target = T;
//
// fn deref<'a>(&'a self) -> &'a T {
// &*self.ptr
// }
//}
//
//impl<T> DerefMut for P<T> {
// fn deref_mut<'a>(&'a mut self) -> &'a mut T {
// &mut *self.ptr
// }
//}
//
//impl<T: 'static + Clone> Clone for P<T> {
// fn clone(&self) -> P<T> {
// P((**self).clone())
// }
//}
//
//impl<T: PartialEq> PartialEq for P<T> {
// fn eq(&self, other: &P<T>) -> bool {
// **self == **other
// }
//}
//
//impl<T: Eq> Eq for P<T> {}
//
//impl<T: Debug> Debug for P<T> {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Debug::fmt(&**self, f)
// }
//}
//impl<T: Display> Display for P<T> {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Display::fmt(&**self, f)
// }
//}
//
//impl<T> fmt::Pointer for P<T> {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// fmt::Pointer::fmt(&self.ptr, f)
// }
//}
//
//impl<T: Hash> Hash for P<T> {
// fn hash<H: Hasher>(&self, state: &mut H) {
// (**self).hash(state);
// }
//}
......@@ -6,24 +6,22 @@ use std::fmt;
use std::collections::HashMap;
use std::sync::RwLock;
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
#[derive(PartialEq, Debug)]
pub struct MuType {
pub id: MuID,
pub name: Option<MuName>,
pub hdr: MuEntityHeader,
pub v: MuType_
}
impl MuType {
pub fn new(id: MuID, v: MuType_) -> MuType {
MuType {
id: id,
name: None,
hdr: MuEntityHeader::unnamed(id),
v: v
}
}
}
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
#[derive(PartialEq, Debug)]
pub enum MuType_ {
/// int <length>
Int (usize),
......@@ -107,7 +105,7 @@ lazy_static! {
pub static ref STRUCT_TAG_MAP : RwLock<HashMap<MuName, StructType_>> = RwLock::new(HashMap::new());
}
#[derive(Clone, PartialEq, Eq, Debug)]
#[derive(PartialEq, Debug)]
pub struct StructType_ {
tys: Vec<P<MuType>>
}
......@@ -325,10 +323,9 @@ macro_rules! is_type (
)
);
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
#[derive(PartialEq, Debug)]
pub struct MuFuncSig {
pub id: MuID,
pub name: Option<MuName>,
pub hdr: MuEntityHeader,
pub ret_tys : Vec<P<MuType>>,
pub arg_tys: Vec<P<MuType>>
}
......
......@@ -77,7 +77,7 @@ impl MachineCode for ASMCode {
}
fn replace_reg(&mut self, from: MuID, to: MuID) {
let to_reg_tag : MuName = backend::all_regs()[to].name.unwrap();
let to_reg_tag : MuName = backend::all_regs().get(&to).unwrap().name().unwrap();
let to_reg_string = "%".to_string() + to_reg_tag;
match self.reg_defines.get(&from) {
......@@ -498,7 +498,7 @@ impl ASMCodeGen {
let id = op.extract_ssa_id().unwrap();
if id < MACHINE_ID_END {
// machine reg
format!("%{}", op.name.unwrap())
format!("%{}", op.name().unwrap())
} else {
// virtual register, use place holder
REG_PLACEHOLDER.clone()
......@@ -921,7 +921,7 @@ impl CodeGenerator for ASMCodeGen {
}
fn emit_jmp(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap();
let dest_name = dest.name().unwrap();
trace!("emit: jmp {}", dest_name);
// symbolic label, we dont need to patch it
......@@ -930,7 +930,7 @@ impl CodeGenerator for ASMCodeGen {
}
fn emit_je(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap();
let dest_name = dest.name().unwrap();
trace!("emit: je {}", dest_name);
let asm = format!("je {}", self.asm_block_label(dest_name));
......@@ -938,7 +938,7 @@ impl CodeGenerator for ASMCodeGen {
}
fn emit_jne(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap();
let dest_name = dest.name().unwrap();
trace!("emit: jne {}", dest_name);
let asm = format!("jne {}", self.asm_block_label(dest_name));
......@@ -946,7 +946,7 @@ impl CodeGenerator for ASMCodeGen {
}
fn emit_ja(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap();
let dest_name = dest.name().unwrap();
trace!("emit: ja {}", dest_name);
let asm = format!("ja {}", self.asm_block_label(dest_name));
......@@ -954,7 +954,7 @@ impl CodeGenerator for ASMCodeGen {
}
fn emit_jae(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap();
let dest_name = dest.name().unwrap();
trace!("emit: jae {}", dest_name);
let asm = format!("jae {}", self.asm_block_label(dest_name));
......@@ -962,7 +962,7 @@ impl CodeGenerator for ASMCodeGen {
}
fn emit_jb(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap();
let dest_name = dest.name().unwrap();
trace!("emit: jb {}", dest_name);
let asm = format!("jb {}", self.asm_block_label(dest_name));
......@@ -970,7 +970,7 @@ impl CodeGenerator for ASMCodeGen {
}
fn emit_jbe(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap();
let dest_name = dest.name().unwrap();
trace!("emit: jbe {}", dest_name);
let asm = format!("jbe {}", self.asm_block_label(dest_name));
......@@ -978,7 +978,7 @@ impl CodeGenerator for ASMCodeGen {
}
fn emit_jg(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap();
let dest_name = dest.name().unwrap();
trace!("emit: jg {}", dest_name);
let asm = format!("jg {}", self.asm_block_label(dest_name));
......@@ -986,7 +986,7 @@ impl CodeGenerator for ASMCodeGen {
}
fn emit_jge(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap();
let dest_name = dest.name().unwrap();
trace!("emit: jge {}", dest_name);
let asm = format!("jge {}", self.asm_block_label(dest_name));
......@@ -994,7 +994,7 @@ impl CodeGenerator for ASMCodeGen {
}
fn emit_jl(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap();
let dest_name = dest.name().unwrap();
trace!("emit: jl {}", dest_name);
let asm = format!("jl {}", self.asm_block_label(dest_name));
......@@ -1002,7 +1002,7 @@ impl CodeGenerator for ASMCodeGen {
}
fn emit_jle(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap();
let dest_name = dest.name().unwrap();
trace!("emit: jle {}", dest_name);
let asm = format!("jle {}", self.asm_block_label(dest_name));
......@@ -1091,7 +1091,7 @@ pub fn emit_code(fv: &mut MuFunctionVersion, vm: &VM) {
let func = funcs.get(&fv.func_id).unwrap().borrow();
let compiled_funcs = vm.compiled_funcs().read().unwrap();
let cf = compiled_funcs.get(&fv.id).unwrap().borrow();
let cf = compiled_funcs.get(&fv.id()).unwrap().borrow();
let code = cf.mc.emit();
......@@ -1100,7 +1100,7 @@ pub fn emit_code(fv: &mut MuFunctionVersion, vm: &VM) {
let mut file_path = path::PathBuf::new();
file_path.push(EMIT_DIR);
file_path.push(func.name.unwrap().to_string() + ".s");
file_path.push(func.name().unwrap().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
......@@ -1135,13 +1135,22 @@ pub fn emit_context(vm: &VM) {
let globals = vm.globals().read().unwrap();
for global in globals.values() {
debug!("emit global: {}", global);
let (size, align) = {
let ty_info = vm.get_backend_type_info(&global.ty);
let alloc_ty = {
match global.v {
Value_::Global(ref ty) => ty,
_ => panic!("expected a global")
}
};
debug!("getting type: {:?}", alloc_ty);
let ty_info = vm.get_backend_type_info(alloc_ty.id());
(ty_info.size, ty_info.alignment)
};
file.write_fmt(format_args!("\t{}\n", directive_globl(symbol(global.name.unwrap())))).unwrap();
file.write_fmt(format_args!("\t{}\n", directive_comm(symbol(global.name.unwrap()), size, align))).unwrap();
file.write_fmt(format_args!("\t{}\n", directive_globl(symbol(global.name().unwrap())))).unwrap();
file.write_fmt(format_args!("\t{}\n", directive_comm(symbol(global.name().unwrap()), size, align))).unwrap();
file.write("\n".as_bytes()).unwrap();
}
......
......@@ -627,7 +627,7 @@ impl <'a> InstructionSelection {
TreeNode_::Value(ref pv) => {
match pv.v {
Value_::Constant(_)
| Value_::Global
| Value_::Global(_)
| Value_::Memory(_) => panic!("expected ireg"),
Value_::SSAVar(_) => {
pv.clone()
......@@ -668,8 +668,7 @@ impl <'a> InstructionSelection {
TreeNode_::Value(ref pv) => {
match pv.v {
Value_::SSAVar(_) => P(Value{
id: vm.next_id(),
name: None,
hdr: MuEntityHeader::unnamed(vm.next_id()),
ty: types::get_referent_ty(& pv.ty).unwrap(),
v: Value_::Memory(MemoryLocation::Address{
base: pv.clone(),
......@@ -678,19 +677,18 @@ impl <'a> InstructionSelection {
scale: None
})
}),
Value_::Global => {
Value_::Global(_) => {
if vm.is_running() {
// get address from vm
unimplemented!()
} else {
// symbolic
P(Value{
id: vm.next_id(),
name: None,
hdr: MuEntityHeader::unnamed(vm.next_id()),
ty: types::get_referent_ty(&pv.ty).unwrap(),
v: Value_::Memory(MemoryLocation::Symbolic{
base: Some(x86_64::RIP.clone()),
label: pv.name.unwrap()
label: pv.name().unwrap()
})
})
}
......@@ -805,7 +803,7 @@ impl CompilerPass for InstructionSelection {
fn visit_function(&mut self, vm: &VM, func: &mut MuFunctionVersion) {
for block_id in func.block_trace.as_ref().unwrap() {
let block = func.content.as_ref().unwrap().get_block(*block_id);
let block_label = block.name.unwrap();
let block_label = block.name().unwrap();
self.backend.start_block(block_label);
......@@ -833,7 +831,7 @@ impl CompilerPass for InstructionSelection {
let mc = self.backend.finish_code();
let compiled_func = CompiledFunction {
func_id: func.func_id,
func_ver_id: func.id,
func_ver_id: func.id(),
temps: HashMap::new(),
mc: mc
};
......
......@@ -16,13 +16,14 @@ use ast::ir::*;
use ast::types::*;
use compiler::backend::RegGroup;
use std::collections::HashMap;
macro_rules! GPR {
($name: expr) => {
{
let id = new_machine_id();
P(Value {
id: id,
name: Some($name),
hdr: MuEntityHeader::named(id, $name),
ty: GPR_TY.clone(),
v: Value_::SSAVar(id)
})
......@@ -35,8 +36,7 @@ macro_rules! FPR {