WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

Commit 6e2649fe authored by qinsoon's avatar qinsoon
Browse files

Merge branch 'develop' into issue82-inf-loop-in-peephole

parents 6007d267 6d862159
...@@ -42,6 +42,28 @@ test:cargo:runtime: ...@@ -42,6 +42,28 @@ test:cargo:runtime:
script: script:
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 ./test-release --color=always test_runtime 2> /dev/null - RUST_BACKTRACE=1 RUST_TEST_THREADS=1 ./test-release --color=always test_runtime 2> /dev/null
.build_muc: &build_muc |
if [ -d "tests/test_muc/mu-tool-compiler" ]; then rm -Rf tests/test_muc/mu-tool-compiler; fi
cd tests/test_muc
git clone https://gitlab.anu.edu.au/mu/mu-tool-compiler
cd mu-tool-compiler
mkdir lib
ln -s $MU_ZEBU/target/release/libmu.so lib/
make
cd ..
testmuc:test_simple:
stage: test
script:
- *build_muc
- LD_LIBRARY_PATH=mu-tool-compiler/lib/ MUC=mu-tool-compiler/muc python2 -m pytest test_simple.py -v
testmuc:test_swapstack:
stage: test
script:
- *build_muc
- LD_LIBRARY_PATH=mu-tool-compiler/lib/ MUC=mu-tool-compiler/muc python2 -m pytest test_thread_and_stack.py -v
testjit:milestones: testjit:milestones:
stage: test stage: test
script: script:
...@@ -60,6 +82,8 @@ testjit:cmpops: ...@@ -60,6 +82,8 @@ testjit:cmpops:
testjit:controlflow: testjit:controlflow:
stage: test stage: test
script: script:
# run this test under test_jit directory
# as a C source file is expected in a relative path to current working directory
- cd tests/test_jit - cd tests/test_jit
- RUST_BACKTRACE=1 pytest test_controlflow.py -v --color=yes - RUST_BACKTRACE=1 pytest test_controlflow.py -v --color=yes
......
...@@ -22,6 +22,8 @@ extern crate gcc; ...@@ -22,6 +22,8 @@ extern crate gcc;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn main() { fn main() {
gcc::Build::new() gcc::Build::new()
.flag("-O3")
.flag("-c")
.file("src/runtime/runtime_c_x64_sysv.c") .file("src/runtime/runtime_c_x64_sysv.c")
.compile("libruntime_c.a"); .compile("libruntime_c.a");
...@@ -39,6 +41,8 @@ fn main() { ...@@ -39,6 +41,8 @@ fn main() {
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
fn main() { fn main() {
gcc::Build::new() gcc::Build::new()
.flag("-O3")
.flag("-c")
.file("src/runtime/runtime_c_aarch64_sysv.c") .file("src/runtime/runtime_c_aarch64_sysv.c")
.compile("libruntime_c.a"); .compile("libruntime_c.a");
......
...@@ -55,5 +55,5 @@ else ...@@ -55,5 +55,5 @@ else
git -C ./RPySOM submodule init git -C ./RPySOM submodule init
git -C ./RPySOM submodule update git -C ./RPySOM submodule update
fi fi
shopt -s extglob
pytest test_*.py -v --color=yes 2>&1 | tee $MU_ZEBU/pytest_out.txt pytest ./test_!(pypy).py -v --color=yes 2>&1 | tee $MU_ZEBU/pytest_out.txt
...@@ -26,4 +26,5 @@ lazy_static = "*" ...@@ -26,4 +26,5 @@ lazy_static = "*"
log = "*" log = "*"
simple_logger = "*" simple_logger = "*"
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = ">= 0.0.5" } rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = ">= 0.0.5" }
regex = "*"
#rodal = { path = "../../../rodal_test/rodal", version = ">= 0.0.5" } #rodal = { path = "../../../rodal_test/rodal", version = ">= 0.0.5" }
...@@ -63,6 +63,20 @@ impl Instruction { ...@@ -63,6 +63,20 @@ impl Instruction {
use inst::Instruction_::*; use inst::Instruction_::*;
match self.v { match self.v {
Return(_) |
ThreadExit |
Throw(_) |
TailCall(_) |
Branch1(_) |
Branch2 { .. } |
Watchpoint { .. } |
WPBranch { .. } |
Call { .. } |
CCall { .. } |
SwapStackExc { .. } |
SwapStackKill { .. } |
Switch { .. } |
ExnInstruction { .. } => true,
BinOp(_, _, _) | BinOp(_, _, _) |
BinOpWithStatus(_, _, _, _) | BinOpWithStatus(_, _, _, _) |
CmpOp(_, _, _) | CmpOp(_, _, _) |
...@@ -78,8 +92,7 @@ impl Instruction { ...@@ -78,8 +92,7 @@ impl Instruction {
NewHybrid(_, _) | NewHybrid(_, _) |
AllocAHybrid(_, _) | AllocAHybrid(_, _) |
NewStack(_) | NewStack(_) |
NewThread(_, _) | NewThread { .. } |
NewThreadExn(_, _) |
NewFrameCursor(_) | NewFrameCursor(_) |
GetIRef(_) | GetIRef(_) |
GetFieldIRef { .. } | GetFieldIRef { .. } |
...@@ -105,20 +118,10 @@ impl Instruction { ...@@ -105,20 +118,10 @@ impl Instruction {
CommonInst_Tr64ToTag(_) | CommonInst_Tr64ToTag(_) |
Move(_) | Move(_) |
PrintHex(_) | PrintHex(_) |
SetRetval(_) => false, SetRetval(_) |
Return(_) | KillStack(_) |
ThreadExit | CurrentStack |
Throw(_) | SwapStackExpr { .. } => false
TailCall(_) |
Branch1(_) |
Branch2 { .. } |
Watchpoint { .. } |
WPBranch { .. } |
Call { .. } |
CCall { .. } |
SwapStack { .. } |
Switch { .. } |
ExnInstruction { .. } => true
} }
} }
...@@ -135,58 +138,65 @@ impl Instruction { ...@@ -135,58 +138,65 @@ impl Instruction {
use inst::Instruction_::*; use inst::Instruction_::*;
match self.v { match self.v {
BinOp(_, _, _) => false, ExprCall { .. } |
BinOpWithStatus(_, _, _, _) => false, ExprCCall { .. } |
CmpOp(_, _, _) => false, Load { .. } |
ConvOp { .. } => false, Store { .. } |
ExprCall { .. } => true, CmpXchg { .. } |
ExprCCall { .. } => true, AtomicRMW { .. } |
Load { .. } => true, New(_) |
Store { .. } => true, AllocA(_) |
CmpXchg { .. } => true, NewHybrid(_, _) |
AtomicRMW { .. } => true, AllocAHybrid(_, _) |
New(_) => true, NewStack(_) |
AllocA(_) => true, NewThread { .. } |
NewHybrid(_, _) => true, NewFrameCursor(_) |
AllocAHybrid(_, _) => true, Fence(_) |
NewStack(_) => true, Return(_) |
NewThread(_, _) => true, ThreadExit |
NewThreadExn(_, _) => true, Throw(_) |
NewFrameCursor(_) => true, TailCall(_) |
GetIRef(_) => false, Branch1(_) |
GetFieldIRef { .. } => false, Branch2 { .. } |
GetElementIRef { .. } => false, Watchpoint { .. } |
ShiftIRef { .. } => false, WPBranch { .. } |
GetVarPartIRef { .. } => false, Call { .. } |
Fence(_) => true, CCall { .. } |
Return(_) => true, SwapStackExpr { .. } |
ThreadExit => true, SwapStackExc { .. } |
Throw(_) => true, SwapStackKill { .. } |
TailCall(_) => true, Switch { .. } |
Branch1(_) => true, ExnInstruction { .. } |
Branch2 { .. } => true, CommonInst_GetThreadLocal |
Select { .. } => false, CommonInst_SetThreadLocal(_) |
Watchpoint { .. } => true, CommonInst_Pin(_) |
WPBranch { .. } => true, CommonInst_Unpin(_) |
Call { .. } => true, CommonInst_GetAddr(_) |
CCall { .. } => true, PrintHex(_) |
SwapStack { .. } => true, SetRetval(_) |
Switch { .. } => true, KillStack(_) => true,
ExnInstruction { .. } => true, BinOp(_, _, _) |
CommonInst_GetThreadLocal => true, BinOpWithStatus(_, _, _, _) |
CommonInst_SetThreadLocal(_) => true, CmpOp(_, _, _) |
CommonInst_Pin(_) | CommonInst_Unpin(_) | CommonInst_GetAddr(_) => true, ConvOp { .. } |
CommonInst_Tr64IsFp(_) | CommonInst_Tr64IsInt(_) | CommonInst_Tr64IsRef(_) => false, GetIRef(_) |
CommonInst_Tr64FromFp(_) | CommonInst_Tr64FromInt(_) | CommonInst_Tr64FromRef(_, _) => { GetFieldIRef { .. } |
false GetElementIRef { .. } |
} ShiftIRef { .. } |
GetVarPartIRef { .. } |
Select { .. } |
CommonInst_Tr64IsFp(_) |
CommonInst_Tr64IsInt(_) |
CommonInst_Tr64IsRef(_) |
CommonInst_Tr64FromFp(_) |
CommonInst_Tr64FromInt(_) |
CommonInst_Tr64FromRef(_, _) |
CommonInst_Tr64ToFp(_) | CommonInst_Tr64ToFp(_) |
CommonInst_Tr64ToInt(_) | CommonInst_Tr64ToInt(_) |
CommonInst_Tr64ToRef(_) | CommonInst_Tr64ToRef(_) |
CommonInst_Tr64ToTag(_) => false, CommonInst_Tr64ToTag(_) |
Move(_) => false, Move(_) |
PrintHex(_) => true, CurrentStack => false
SetRetval(_) => true
} }
} }
...@@ -199,9 +209,8 @@ impl Instruction { ...@@ -199,9 +209,8 @@ impl Instruction {
Watchpoint { .. } | Watchpoint { .. } |
Call { .. } | Call { .. } |
CCall { .. } | CCall { .. } |
SwapStack { .. } | SwapStackExc { .. } |
ExnInstruction { .. } => true, ExnInstruction { .. } => true,
BinOp(_, _, _) | BinOp(_, _, _) |
BinOpWithStatus(_, _, _, _) | BinOpWithStatus(_, _, _, _) |
CmpOp(_, _, _) | CmpOp(_, _, _) |
...@@ -217,8 +226,7 @@ impl Instruction { ...@@ -217,8 +226,7 @@ impl Instruction {
NewHybrid(_, _) | NewHybrid(_, _) |
AllocAHybrid(_, _) | AllocAHybrid(_, _) |
NewStack(_) | NewStack(_) |
NewThread(_, _) | NewThread { .. } |
NewThreadExn(_, _) |
NewFrameCursor(_) | NewFrameCursor(_) |
GetIRef(_) | GetIRef(_) |
GetFieldIRef { .. } | GetFieldIRef { .. } |
...@@ -252,7 +260,11 @@ impl Instruction { ...@@ -252,7 +260,11 @@ impl Instruction {
CommonInst_Tr64ToTag(_) | CommonInst_Tr64ToTag(_) |
Move(_) | Move(_) |
PrintHex(_) | PrintHex(_) |
SetRetval(_) => false SetRetval(_) |
KillStack(_) |
CurrentStack |
SwapStackExpr { .. } |
SwapStackKill { .. } => false
} }
} }
...@@ -269,9 +281,8 @@ impl Instruction { ...@@ -269,9 +281,8 @@ impl Instruction {
Watchpoint { ref resume, .. } | Watchpoint { ref resume, .. } |
Call { ref resume, .. } | Call { ref resume, .. } |
CCall { ref resume, .. } | CCall { ref resume, .. } |
SwapStack { ref resume, .. } | SwapStackExc { ref resume, .. } |
ExnInstruction { ref resume, .. } => Some(resume.exn_dest.target), ExnInstruction { ref resume, .. } => Some(resume.exn_dest.target),
BinOp(_, _, _) | BinOp(_, _, _) |
BinOpWithStatus(_, _, _, _) | BinOpWithStatus(_, _, _, _) |
CmpOp(_, _, _) | CmpOp(_, _, _) |
...@@ -287,8 +298,7 @@ impl Instruction { ...@@ -287,8 +298,7 @@ impl Instruction {
NewHybrid(_, _) | NewHybrid(_, _) |
AllocAHybrid(_, _) | AllocAHybrid(_, _) |
NewStack(_) | NewStack(_) |
NewThread(_, _) | NewThread { .. } |
NewThreadExn(_, _) |
NewFrameCursor(_) | NewFrameCursor(_) |
GetIRef(_) | GetIRef(_) |
GetFieldIRef { .. } | GetFieldIRef { .. } |
...@@ -322,7 +332,11 @@ impl Instruction { ...@@ -322,7 +332,11 @@ impl Instruction {
CommonInst_Tr64ToTag(_) | CommonInst_Tr64ToTag(_) |
Move(_) | Move(_) |
PrintHex(_) | PrintHex(_) |
SetRetval(_) => None SetRetval(_) |
KillStack(_) |
CurrentStack |
SwapStackExpr { .. } |
SwapStackKill { .. } => None
} }
} }
...@@ -433,13 +447,20 @@ pub enum Instruction_ { ...@@ -433,13 +447,20 @@ pub enum Instruction_ {
/// args: functionref of the entry function /// args: functionref of the entry function
NewStack(OpIndex), NewStack(OpIndex),
/// kill the given Mu stack
KillStack(OpIndex),
/// return stackref for the current stack
CurrentStack,
/// create a new Mu thread, yields thread reference /// create a new Mu thread, yields thread reference
/// args: stackref of a Mu stack, a list of arguments /// args: stackref of a Mu stack, a list of arguments
NewThread(OpIndex, Vec<OpIndex>), // stack, args NewThread {
stack: OpIndex,
/// create a new Mu thread, yields thread reference (thread resumes with exceptional value) thread_local: Option<OpIndex>,
/// args: stackref of a Mu stack, an exceptional value is_exception: bool,
NewThreadExn(OpIndex, OpIndex), // stack, exception args: Vec<OpIndex>
},
/// create a frame cursor reference /// create a frame cursor reference
/// args: stackref of a Mu stack /// args: stackref of a Mu stack
...@@ -539,15 +560,29 @@ pub enum Instruction_ { ...@@ -539,15 +560,29 @@ pub enum Instruction_ {
resume: ResumptionData resume: ResumptionData
}, },
/// swapstack. swap current Mu stack with the named Mu stack, /// A swap stack with an exception clause (i.e. uses the RET_WITH form)
/// and continue with specified resumption SwapStackExc {
SwapStack {
stack: OpIndex, stack: OpIndex,
is_exception: bool, is_exception: bool,
args: Vec<OpIndex>, args: Vec<OpIndex>,
resume: ResumptionData resume: ResumptionData
}, },
/// A swap stack without an exception clause that is not a terminator
/// (i.e. uses the RET_WITH form)
SwapStackExpr {
stack: OpIndex,
is_exception: bool,
args: Vec<OpIndex>
},
/// A swapstack without an exception clause that is a terminator (i.e. one with KILL_OLD)
SwapStackKill {
stack: OpIndex,
is_exception: bool,
args: Vec<OpIndex>
},
/// a multiway branch /// a multiway branch
Switch { Switch {
cond: OpIndex, cond: OpIndex,
...@@ -685,17 +720,24 @@ impl Instruction_ { ...@@ -685,17 +720,24 @@ impl Instruction_ {
&Instruction_::AllocA(ref ty) => format!("ALLOCA {}", ty), &Instruction_::AllocA(ref ty) => format!("ALLOCA {}", ty),
&Instruction_::NewHybrid(ref ty, len) => format!("NEWHYBRID {} {}", ty, ops[len]), &Instruction_::NewHybrid(ref ty, len) => format!("NEWHYBRID {} {}", ty, ops[len]),
&Instruction_::AllocAHybrid(ref ty, len) => format!("ALLOCAHYBRID {} {}", ty, ops[len]), &Instruction_::AllocAHybrid(ref ty, len) => format!("ALLOCAHYBRID {} {}", ty, ops[len]),
&Instruction_::NewStack(func) => format!("NEWSTACK {}", ops[func]), &Instruction_::NewStack(func) => format!("NEW_STACK {}", ops[func]),
&Instruction_::NewThread(stack, ref args) => { &Instruction_::NewThread {
stack,
thread_local,
is_exception,
ref args
} => {
let thread_local = thread_local
.map(|t| format!("{}", ops[t]))
.unwrap_or("NULL".to_string());
format!( format!(
"NEWTHREAD {} PASS_VALUES {}", "SWAPSTACK {} THREADLOCAL({}) {} {}",
ops[stack], ops[stack],
op_vector_str(args, ops) thread_local,
is_exception,
op_vector_str(args, ops),
) )
} }
&Instruction_::NewThreadExn(stack, exn) => {
format!("NEWTHREAD {} THROW_EXC {}", ops[stack], ops[exn])
}
&Instruction_::NewFrameCursor(stack) => format!("NEWFRAMECURSOR {}", ops[stack]), &Instruction_::NewFrameCursor(stack) => format!("NEWFRAMECURSOR {}", ops[stack]),
&Instruction_::GetIRef(reference) => format!("GETIREF {}", ops[reference]), &Instruction_::GetIRef(reference) => format!("GETIREF {}", ops[reference]),
&Instruction_::GetFieldIRef { &Instruction_::GetFieldIRef {
...@@ -731,6 +773,8 @@ impl Instruction_ { ...@@ -731,6 +773,8 @@ impl Instruction_ {
&Instruction_::Return(ref vals) => format!("RET {}", op_vector_str(vals, ops)), &Instruction_::Return(ref vals) => format!("RET {}", op_vector_str(vals, ops)),
&Instruction_::ThreadExit => "THREADEXIT".to_string(), &Instruction_::ThreadExit => "THREADEXIT".to_string(),
&Instruction_::CurrentStack => "CURRENT_STACK".to_string(),
&Instruction_::KillStack(s) => format!("RET {}", ops[s]),
&Instruction_::Throw(exn_obj) => format!("THROW {}", ops[exn_obj]), &Instruction_::Throw(exn_obj) => format!("THROW {}", ops[exn_obj]),
&Instruction_::TailCall(ref call) => format!("TAILCALL {}", call.debug_str(ops)), &Instruction_::TailCall(ref call) => format!("TAILCALL {}", call.debug_str(ops)),
&Instruction_::Branch1(ref dest) => format!("BRANCH {}", dest.debug_str(ops)), &Instruction_::Branch1(ref dest) => format!("BRANCH {}", dest.debug_str(ops)),
...@@ -797,7 +841,19 @@ impl Instruction_ { ...@@ -797,7 +841,19 @@ impl Instruction_ {
ref data, ref data,
ref resume ref resume
} => format!("CCALL {} {}", data.debug_str(ops), resume.debug_str(ops)), } => format!("CCALL {} {}", data.debug_str(ops), resume.debug_str(ops)),
&Instruction_::SwapStack { &Instruction_::SwapStackExpr {
stack,
is_exception,
ref args
} => {
format!(
"SWAPSTACK {} {} {}",
ops[stack],
is_exception,
op_vector_str(args, ops),
)
}
&Instruction_::SwapStackExc {
stack, stack,
is_exception, is_exception,
ref args, ref args,
...@@ -811,6 +867,20 @@ impl Instruction_ { ...@@ -811,6 +867,20 @@ impl Instruction_ {
resume.debug_str(ops) resume.debug_str(ops)
) )
} }
&Instruction_::SwapStackKill {
stack,
is_exception,
ref args
} => {
format!(
"SWAPSTACK {} {} {}",
ops[stack],
is_exception,
op_vector_str(args, ops),
)
}
&Instruction_::Switch { &Instruction_::Switch {
cond, cond,
ref default, ref default,
...@@ -948,7 +1018,7 @@ impl fmt::Debug for BinOpStatus { ...@@ -948,7 +1018,7 @@ impl fmt::Debug for BinOpStatus {
} }
} }
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum MemoryOrder { pub enum MemoryOrder {
NotAtomic, NotAtomic,
Relaxed, Relaxed,
......
...@@ -795,7 +795,7 @@ impl BlockContent { ...@@ -795,7 +795,7 @@ impl BlockContent {
} }
Instruction_::Call { ref resume, .. } | Instruction_::Call { ref resume, .. } |
Instruction_::CCall { ref resume, .. } | Instruction_::CCall { ref resume, .. } |
Instruction_::SwapStack { ref resume, .. } | Instruction_::SwapStackExc { ref resume, .. } |
Instruction_::ExnInstruction { ref resume, .. } => { Instruction_::ExnInstruction { ref resume, .. } => {
let mut live_outs = vec![]; let mut live_outs = vec![];
live_outs.append(&mut resume.normal_dest.get_arguments(&ops)); live_outs.append(&mut resume.normal_dest.get_arguments(&ops));
...@@ -1012,6 +1012,23 @@ impl Value { ...@@ -1012,6 +1012,23 @@ impl Value {
} }
} }
pub fn is_const_zero(&self) -> bool {
match self.v {
Value_::Constant(Constant::Int(val)) if val == 0 => true,
Value_::Constant(Constant::Double(val)) if val == 0f64 => true,
Value_::Constant(Constant::Float(val)) if val == 0f32 => true,
Value_::Constant(Constant::IntEx(ref vec)) => {
if vec.iter().all(|x| *x == 0) {
true
} else {
false
}
}
Value_::Constant(Constant::NullRef) => true,
_ => false
}
}
/// disguises a value as another type. /// disguises a value as another type.
/// This is usually used for treat an integer type as an integer of a different length /// This is usually used for treat an integer type as an integer of a different length
/// This method is unsafe /// This method is unsafe
...@@ -1077,7 +1094,7 @@ impl Value { ...@@ -1077,7 +1094,7 @@ impl Value {
} }
} }
const DISPLAY_ID: bool = false; const DISPLAY_ID: bool = true;
const DISPLAY_TYPE: bool = true; const DISPLAY_TYPE: bool = true;
const PRINT_ABBREVIATE_NAME: bool = true; const PRINT_ABBREVIATE_NAME: bool = true;
.