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 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 {
{
let id = new_machine_id();
P(Value {
id: id,
name: Some($name),
hdr: MuEntityHeader::named(id, $name),
ty: FPR_TY.clone(),
v: Value_::SSAVar(id)
})
......@@ -171,41 +171,44 @@ pub const GPR_COUNT : usize = 16;