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 c3ba71ac authored by John Zhang's avatar John Zhang
Browse files

Merge branch 'master' into ci-script

parents 00c57362 a241c754
**/target/*
**/__pycache__/*
**/.cache/*
emit/*
**/temp/*
Cargo.lock
......
......@@ -35,21 +35,21 @@ test:cargo:api:
dependencies:
- build_test
script:
- RUST_BACKTRACE=1 CC=clang cargo test test_api
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo test test_api
test:cargo:ir:
stage: test
dependencies:
- build_test
script:
- RUST_BACKTRACE=1 CC=clang cargo test test_ir
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo test test_ir
test:cargo:compiler:
stage: test
dependencies:
- build_test
script:
- RUST_BACKTRACE=1 CC=clang cargo test test_compiler
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo test test_compiler
test:cargo:runtime:
stage: test
......@@ -63,18 +63,27 @@ testjit:milestones:
dependencies:
- build_test
script:
- RUST_BACKTRACE=1 pytest tests/test_jit/test_milestones.py
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo build 2>/dev/null
- RUST_BACKTRACE=1 pytest tests/test_jit/test_milestones.py
testjit:binops:
stage: test
dependencies:
- build_test
script:
- RUST_BACKTRACE=1 pytest tests/test_jit/test_binops.py
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo build 2>/dev/null
- RUST_BACKTRACE=1 pytest tests/test_jit/test_binops.py
testjit:cmpops:
stage: test
dependencies:
- build_test
script:
- RUST_BACKTRACE=1 pytest tests/test_jit/test_cmpops.py
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo build 2>/dev/null
- RUST_BACKTRACE=1 pytest tests/test_jit/test_cmpops.py
testjit:cmpops:
stage: test
script:
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo build 2>/dev/null
- RUST_BACKTRACE=1 pytest tests/test_jit/test_convops.py
\ No newline at end of file
......@@ -64,6 +64,8 @@ echo "KERNEL: $KERNEL"
echo "ARCH: $MACH"
echo "---------"
rm emit/*
if [ "$OS" == "linux" ]; then
RUSTFLAGS=-Zincremental=target/incr-cache RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang-3.8 cargo test "$@"
elif [ "$OS" == "Darwin" ]; then
......
......@@ -91,6 +91,12 @@ pub enum Instruction_ {
BinOp(BinOp, OpIndex, OpIndex),
CmpOp(CmpOp, OpIndex, OpIndex),
ConvOp{
operation: ConvOp,
from_ty: P<MuType>,
to_ty: P<MuType>,
operand: OpIndex
},
// yields a tuple of results from the call
ExprCall{
......@@ -254,6 +260,9 @@ impl Instruction_ {
match self {
&Instruction_::BinOp(op, op1, op2) => format!("{:?} {} {}", op, ops[op1], ops[op2]),
&Instruction_::CmpOp(op, op1, op2) => format!("{:?} {} {}", op, ops[op1], ops[op2]),
&Instruction_::ConvOp{operation, ref from_ty, ref to_ty, operand} => {
format!("{:?} {} {} {}", operation, from_ty, to_ty, ops[operand])
}
&Instruction_::ExprCall{ref data, is_abort} => {
let abort = select_value!(is_abort, "ABORT_ON_EXN", "RETHROW");
format!("CALL {} {}", data.debug_str(ops), abort)
......
......@@ -4,6 +4,7 @@ use inst::*;
use op::*;
use utils::vec_utils;
use utils::Address;
use std::collections::HashMap;
use std::fmt;
......@@ -735,6 +736,8 @@ pub enum Constant {
FuncRef(MuID),
UFuncRef(MuID),
Vector(Vec<Constant>),
//Pointer(Address),
NullRef,
}
impl fmt::Display for Constant {
......@@ -756,6 +759,7 @@ impl fmt::Display for Constant {
}
write!(f, "]")
}
&Constant::NullRef => write!(f, "NullRef"),
}
}
}
......
......@@ -5,6 +5,7 @@ pub fn is_terminal_inst(inst: &Instruction_) -> bool {
match inst {
&BinOp(_, _, _)
| &CmpOp(_, _, _)
| &ConvOp{..}
| &ExprCall{..}
| &Load{..}
| &Store{..}
......@@ -49,6 +50,7 @@ pub fn has_side_effect(inst: &Instruction_) -> bool {
match inst {
&BinOp(_, _, _) => false,
&CmpOp(_, _, _) => false,
&ConvOp{..} => false,
&ExprCall{..} => true,
&Load{..} => true,
&Store{..} => true,
......
......@@ -35,6 +35,7 @@ pub enum OpCode {
// expression
Binary(BinOp),
Comparison(CmpOp),
Conversion(ConvOp),
AtomicRMW(AtomicRMWOp),
ExprCall,
......@@ -172,6 +173,22 @@ pub enum CmpOp {
FUNO
}
#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub enum ConvOp {
TRUNC,
ZEXT,
SEXT,
FPTRUNC,
FPEXT,
FPTOUI,
FPTOSI,
UITOFP,
SITOFP,
BITCAST,
REFCAST,
PTRCAST
}
#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub enum AtomicRMWOp {
XCHG,
......@@ -207,6 +224,7 @@ pub fn pick_op_code_for_inst(inst: &Instruction) -> OpCode {
match inst.v {
Instruction_::BinOp(op, _, _) => OpCode::Binary(op),
Instruction_::CmpOp(op, _, _) => OpCode::Comparison(op),
Instruction_::ConvOp{operation, ..} => OpCode::Conversion(operation),
Instruction_::AtomicRMW{op, ..} => OpCode::AtomicRMW(op),
Instruction_::ExprCall{..} => OpCode::ExprCall,
Instruction_::Load{..} => OpCode::Load,
......
......@@ -12,6 +12,14 @@ lazy_static! {
pub static ref ADDRESS_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::int(POINTER_SIZE * 8))
);
pub static ref UINT8_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::int(8))
);
pub static ref UINT16_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::int(16))
);
pub static ref UINT32_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::int(32))
......@@ -27,6 +35,8 @@ lazy_static! {
pub static ref INTERNAL_TYPES : Vec<P<MuType>> = vec![
ADDRESS_TYPE.clone(),
UINT8_TYPE.clone(),
UINT16_TYPE.clone(),
UINT32_TYPE.clone(),
UINT64_TYPE.clone(),
DOUBLE_TYPE.clone()
......
......@@ -625,7 +625,7 @@ impl ASMInst {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq, Eq)]
struct ASMLocation {
line: usize,
index: usize,
......@@ -1062,22 +1062,335 @@ impl ASMCodeGen {
}
}
#[inline(always)]
fn op_postfix(op_len: usize) -> &'static str {
match op_len {
8 => "b",
16 => "w",
32 => "l",
64 => "q",
_ => panic!("unexpected op size: {}", op_len)
}
}
// general instruction emission
macro_rules! binop_no_def_r_r {
($func_name: ident, $inst: expr, $op_len: expr) => {
fn $func_name (&mut self, op1: &P<Value>, op2: &P<Value>) {
// with postfix
let inst = $inst.to_string() + &op_postfix($op_len);
trace!("emit: {} {} {}", inst, op1, op2);
let (reg1, id1, loc1) = self.prepare_reg(op1, inst.len() + 1);
let (reg2, id2, loc2) = self.prepare_reg(op2, inst.len() + 1 + reg1.len() + 1);
let asm = format!("{} {},{}", inst, reg1, reg2);
self.add_asm_inst(
asm,
hashmap!{},
hashmap!{
id1 => vec![loc1],
id2 => vec![loc2]
},
false
)
}
}
}
macro_rules! binop_no_def_r_imm {
($func_name: ident, $inst: expr, $op_len: expr, $imm_ty: ty) => {
fn $func_name (&mut self, op1: &P<Value>, op2: $imm_ty) {
let inst = $inst.to_string() + &op_postfix($op_len);
trace!("emit: {} {} {}", inst, op1, op2);
let (reg1, id1, loc1) = self.prepare_reg(op1, inst.len() + 1 + 1 + op2.to_string().len() + 1);
let asm = format!("{} ${},{}", inst, op2, reg1);
self.add_asm_inst(
asm,
hashmap!{},
hashmap!{
id1 => vec![loc1]
},
false
)
}
}
}
macro_rules! binop_no_def_r_mem {
($func_name: ident, $inst:expr, $op_len: expr) => {
fn $func_name (&mut self, op1: &P<Value>, op2: &P<Value>) {
let inst = $inst.to_string() + &op_postfix($op_len);
trace!("emit: {} {} {}", inst, op1, op2);
let (reg, id1, loc1) = self.prepare_reg(op1, inst.len() + 1);
let (mem, mut uses) = self.prepare_mem(op2, inst.len() + 1 + reg.len() + 1);
let asm = format!("{} {},{}", inst, reg, mem);
// merge use vec
if uses.contains_key(&id1) {
let mut locs = uses.get_mut(&id1).unwrap();
vec_utils::add_unique(locs, loc1.clone());
} else {
uses.insert(id1, vec![loc1]);
}
self.add_asm_inst(
asm,
hashmap!{},
uses,
true
)
}
}
}
macro_rules! binop_def_r_r {
($func_name: ident, $inst: expr, $op_len: expr) => {
fn $func_name (&mut self, dest: &P<Value>, src: &P<Value>) {
let inst = $inst.to_string() + &op_postfix($op_len);
trace!("emit: {} {}, {} -> {}", inst, src, dest, dest);
let (reg1, id1, loc1) = self.prepare_reg(src, inst.len() + 1);
let (reg2, id2, loc2) = self.prepare_reg(dest, inst.len() + 1 + reg1.len() + 1);
let asm = format!("{} {},{}", inst, reg1, reg2);
self.add_asm_inst(
asm,
hashmap!{
id2 => vec![loc2.clone()]
},
hashmap!{
id1 => vec![loc1],
id2 => vec![loc2]
},
false
)
}
}
}
macro_rules! binop_def_r_imm {
($func_name: ident, $inst: expr, $op_len: expr, $imm_ty: ty) => {
fn $func_name (&mut self, dest: &P<Value>, src: $imm_ty) {
let inst = $inst.to_string() + &op_postfix($op_len);
trace!("emit: {} {}, {} -> {}", inst, src, dest, dest);
let (reg1, id1, loc1) = self.prepare_reg(dest, inst.len() + 1 + 1 + src.to_string().len() + 1);
let asm = format!("{} ${},{}", inst, src, reg1);
self.add_asm_inst(
asm,
hashmap!{
id1 => vec![loc1.clone()]
},
hashmap!{
id1 => vec![loc1]
},
false
)
}
}
}
macro_rules! binop_def_r_mem {
($func_name: ident, $inst: expr, $op_len: expr) => {
fn $func_name (&mut self, dest: &P<Value>, src: &P<Value>) {
let inst = $inst.to_string() + &op_postfix($op_len);
trace!("emit: {} {}, {} -> {}", inst, src, dest, dest);
let (mem, mut uses) = self.prepare_mem(src, inst.len() + 1);
let (reg, id1, loc1) = self.prepare_reg(dest, inst.len() + 1 + mem.len() + 1);
if uses.contains_key(&id1) {
let mut locs = uses.get_mut(&id1).unwrap();
vec_utils::add_unique(locs, loc1.clone());
} else {
uses.insert(id1, vec![loc1.clone()]);
}
let asm = format!("{} {},{}", inst, mem, reg);
self.add_asm_inst(
asm,
hashmap!{
id1 => vec![loc1]
},
uses,
true
)
}
}
}
macro_rules! mov_r_r {
($func_name: ident, $inst: expr, $op_len: expr) => {
fn $func_name (&mut self, dest: &P<Value>, src: &P<Value>) {
let inst = $inst.to_string() + &op_postfix($op_len);
trace!("emit: {} {} -> {}", inst, src, dest);
let (reg1, id1, loc1) = self.prepare_reg(src, inst.len() + 1);
let (reg2, id2, loc2) = self.prepare_reg(dest, inst.len() + 1 + reg1.len() + 1);
let asm = format!("{} {},{}", inst, reg1, reg2);
self.add_asm_inst(
asm,
hashmap!{
id2 => vec![loc2]
},
hashmap!{
id1 => vec![loc1]
},
false
)
}
}
}
macro_rules! mov_r_imm {
($func_name: ident, $inst: expr, $op_len: expr, $imm_ty: ty) => {
fn $func_name (&mut self, dest: &P<Value>, src: $imm_ty) {
let inst = $inst.to_string() + &op_postfix($op_len);
trace!("emit: {} {} -> {}", inst, src, dest);
let (reg1, id1, loc1) = self.prepare_reg(dest, inst.len() + 1 + 1 + src.to_string().len() + 1);
let asm = format!("{} ${},{}", inst, src, reg1);
self.add_asm_inst(
asm,
hashmap!{
id1 => vec![loc1]
},
hashmap!{},
false
)
}
}
}
/// load
macro_rules! mov_r_mem {
($func_name: ident, $inst: expr, $op_len: expr) => {
fn $func_name (&mut self, dest: &P<Value>, src: &P<Value>) {
let inst = $inst.to_string() + &op_postfix($op_len);
trace!("emit: {} {} -> {}", inst, src, dest);
let (mem, uses) = self.prepare_mem(src, inst.len() + 1);
let (reg, id2, loc2) = self.prepare_reg(dest, inst.len() + 1 + mem.len() + 1);
let asm = format!("{} {},{}", inst, mem, reg);
self.add_asm_inst(
asm,
hashmap!{
id2 => vec![loc2]
},
uses,
true
)
}
}
}
/// store
macro_rules! mov_mem_r {
($func_name: ident, $inst: expr, $op_len: expr) => {
fn $func_name (&mut self, dest: &P<Value>, src: &P<Value>) {
let inst = $inst.to_string() + &op_postfix($op_len);
trace!("emit: {} {} -> {}", inst, src, dest);
let (reg, id1, loc1) = self.prepare_reg(src, inst.len() + 1);
let (mem, mut uses) = self.prepare_mem(dest, inst.len() + 1 + reg.len() + 1);
// the register we used for the memory location is counted as 'use'
// use the vec from mem as 'use' (push use reg from src to it)
if uses.contains_key(&id1) {
let mut locs = uses.get_mut(&id1).unwrap();
vec_utils::add_unique(locs, loc1);
} else {
uses.insert(id1, vec![loc1]);
}
let asm = format!("{} {},{}", inst, reg, mem);
self.add_asm_inst(
asm,
hashmap!{},
uses,
true
)
}
}
}
macro_rules! mov_mem_imm {
($func_name: ident, $inst: expr, $op_len: expr, $imm_ty: ty) => {
fn $func_name (&mut self, dest: &P<Value>, src: $imm_ty) {
let inst = $inst.to_string() + &op_postfix($op_len);
trace!("emit: {} {} -> {}", inst, src, dest);
let (mem, uses) = self.prepare_mem(dest, inst.len() + 1 + 1 + src.to_string().len() + 1);
let asm = format!("{} ${},{}", inst, src, mem);
self.add_asm_inst(
asm,
hashmap!{},
uses,
true
)
}
}
}
macro_rules! emit_lea_r {
($func_name: ident, $op_len: expr) => {
fn $func_name (&mut self, dest: &P<Value>, src: &P<Value>) {
trace!("emit: lea {} -> {}", src, dest);
let (mem, uses) = self.prepare_mem(src, 4 + 1);
let (reg, id2, loc2) = self.prepare_reg(dest, 4 + 1 + mem.len() + 1);
let asm = format!("lea{} {},{}", op_postfix($op_len), mem, reg);
self.add_asm_inst(
asm,
hashmap!{
id2 => vec![loc2]
},
uses,
true
)
}
}
}
impl CodeGenerator for ASMCodeGen {
fn start_code(&mut self, func_name: MuName) -> ValueLocation {
self.cur = Some(Box::new(ASMCode {
name: func_name.clone(),
code: vec![],
blocks: hashmap!{},
}));
name: func_name.clone(),
code: vec![],
blocks: hashmap! {},
}));
// to link with C sources via gcc
let func_symbol = symbol(func_name.clone());
self.add_asm_symbolic(directive_globl(func_symbol.clone()));
self.add_asm_symbolic(format!("{}:", func_symbol.clone()));
ValueLocation::Relocatable(RegGroup::GPR, func_name)
}
fn finish_code(&mut self, func_name: MuName) -> (Box<MachineCode + Sync + Send>, ValueLocation) {
let func_end = {
let mut symbol = func_name.clone();
......@@ -1086,9 +1399,9 @@ impl CodeGenerator for ASMCodeGen {
};
self.add_asm_symbolic(directive_globl(symbol(func_end.clone())));
self.add_asm_symbolic(format!("{}:", symbol(func_end.clone())));
self.control_flow_analysis();
(
self.cur.take().unwrap(),
ValueLocation::Relocatable(RegGroup::GPR, func_end)
......@@ -1099,7 +1412,7 @@ impl CodeGenerator for ASMCodeGen {
self.cur = Some(Box::new(ASMCode {
name: "snippet".to_string(),
code: vec![],
blocks: hashmap!{}
blocks: hashmap! {}
}));
}
......@@ -1109,10 +1422,10 @@ impl CodeGenerator for ASMCodeGen {
fn print_cur_code(&self) {
println!("");
if self.cur.is_some() {
let code = self.cur.as_ref().unwrap();
println!("code for {}: ", code.name);
let n_insts = code.code.len();
for i in 0..n_insts {
......@@ -1122,10 +1435,10 @@ impl CodeGenerator for ASMCodeGen {
} else {
println!("no current code");
}
println!("");
}
fn start_block(&mut self, block_name: MuName) {
let label = format!("{}:", symbol(self.mangle_block_label(block_name.clone())));