To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

Commit c3ba71ac authored by John Zhang's avatar John Zhang
Browse files

Merge branch 'master' into ci-script

parents 00c57362 a241c754
**/target/* **/target/*
**/__pycache__/* **/__pycache__/*
**/.cache/*
emit/* emit/*
**/temp/* **/temp/*
Cargo.lock Cargo.lock
......
...@@ -35,21 +35,21 @@ test:cargo:api: ...@@ -35,21 +35,21 @@ test:cargo:api:
dependencies: dependencies:
- build_test - build_test
script: 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: test:cargo:ir:
stage: test stage: test
dependencies: dependencies:
- build_test - build_test
script: 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: test:cargo:compiler:
stage: test stage: test
dependencies: dependencies:
- build_test - build_test
script: 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: test:cargo:runtime:
stage: test stage: test
...@@ -63,18 +63,27 @@ testjit:milestones: ...@@ -63,18 +63,27 @@ testjit:milestones:
dependencies: dependencies:
- build_test - build_test
script: 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: testjit:binops:
stage: test stage: test
dependencies: dependencies:
- build_test - build_test
script: 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: testjit:cmpops:
stage: test stage: test
dependencies: dependencies:
- build_test - build_test
script: 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" ...@@ -64,6 +64,8 @@ echo "KERNEL: $KERNEL"
echo "ARCH: $MACH" echo "ARCH: $MACH"
echo "---------" echo "---------"
rm emit/*
if [ "$OS" == "linux" ]; then if [ "$OS" == "linux" ]; then
RUSTFLAGS=-Zincremental=target/incr-cache RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang-3.8 cargo test "$@" RUSTFLAGS=-Zincremental=target/incr-cache RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang-3.8 cargo test "$@"
elif [ "$OS" == "Darwin" ]; then elif [ "$OS" == "Darwin" ]; then
......
...@@ -91,6 +91,12 @@ pub enum Instruction_ { ...@@ -91,6 +91,12 @@ pub enum Instruction_ {
BinOp(BinOp, OpIndex, OpIndex), BinOp(BinOp, OpIndex, OpIndex),
CmpOp(CmpOp, 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 // yields a tuple of results from the call
ExprCall{ ExprCall{
...@@ -254,6 +260,9 @@ impl Instruction_ { ...@@ -254,6 +260,9 @@ impl Instruction_ {
match self { match self {
&Instruction_::BinOp(op, op1, op2) => format!("{:?} {} {}", op, ops[op1], ops[op2]), &Instruction_::BinOp(op, op1, op2) => format!("{:?} {} {}", op, ops[op1], ops[op2]),
&Instruction_::CmpOp(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} => { &Instruction_::ExprCall{ref data, is_abort} => {
let abort = select_value!(is_abort, "ABORT_ON_EXN", "RETHROW"); let abort = select_value!(is_abort, "ABORT_ON_EXN", "RETHROW");
format!("CALL {} {}", data.debug_str(ops), abort) format!("CALL {} {}", data.debug_str(ops), abort)
......
...@@ -4,6 +4,7 @@ use inst::*; ...@@ -4,6 +4,7 @@ use inst::*;
use op::*; use op::*;
use utils::vec_utils; use utils::vec_utils;
use utils::Address;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt; use std::fmt;
...@@ -735,6 +736,8 @@ pub enum Constant { ...@@ -735,6 +736,8 @@ pub enum Constant {
FuncRef(MuID), FuncRef(MuID),
UFuncRef(MuID), UFuncRef(MuID),
Vector(Vec<Constant>), Vector(Vec<Constant>),
//Pointer(Address),
NullRef,
} }
impl fmt::Display for Constant { impl fmt::Display for Constant {
...@@ -756,6 +759,7 @@ impl fmt::Display for Constant { ...@@ -756,6 +759,7 @@ impl fmt::Display for Constant {
} }
write!(f, "]") write!(f, "]")
} }
&Constant::NullRef => write!(f, "NullRef"),
} }
} }
} }
......
...@@ -5,6 +5,7 @@ pub fn is_terminal_inst(inst: &Instruction_) -> bool { ...@@ -5,6 +5,7 @@ pub fn is_terminal_inst(inst: &Instruction_) -> bool {
match inst { match inst {
&BinOp(_, _, _) &BinOp(_, _, _)
| &CmpOp(_, _, _) | &CmpOp(_, _, _)
| &ConvOp{..}
| &ExprCall{..} | &ExprCall{..}
| &Load{..} | &Load{..}
| &Store{..} | &Store{..}
...@@ -49,6 +50,7 @@ pub fn has_side_effect(inst: &Instruction_) -> bool { ...@@ -49,6 +50,7 @@ pub fn has_side_effect(inst: &Instruction_) -> bool {
match inst { match inst {
&BinOp(_, _, _) => false, &BinOp(_, _, _) => false,
&CmpOp(_, _, _) => false, &CmpOp(_, _, _) => false,
&ConvOp{..} => false,
&ExprCall{..} => true, &ExprCall{..} => true,
&Load{..} => true, &Load{..} => true,
&Store{..} => true, &Store{..} => true,
......
...@@ -35,6 +35,7 @@ pub enum OpCode { ...@@ -35,6 +35,7 @@ pub enum OpCode {
// expression // expression
Binary(BinOp), Binary(BinOp),
Comparison(CmpOp), Comparison(CmpOp),
Conversion(ConvOp),
AtomicRMW(AtomicRMWOp), AtomicRMW(AtomicRMWOp),
ExprCall, ExprCall,
...@@ -172,6 +173,22 @@ pub enum CmpOp { ...@@ -172,6 +173,22 @@ pub enum CmpOp {
FUNO 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)] #[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub enum AtomicRMWOp { pub enum AtomicRMWOp {
XCHG, XCHG,
...@@ -207,6 +224,7 @@ pub fn pick_op_code_for_inst(inst: &Instruction) -> OpCode { ...@@ -207,6 +224,7 @@ pub fn pick_op_code_for_inst(inst: &Instruction) -> OpCode {
match inst.v { match inst.v {
Instruction_::BinOp(op, _, _) => OpCode::Binary(op), Instruction_::BinOp(op, _, _) => OpCode::Binary(op),
Instruction_::CmpOp(op, _, _) => OpCode::Comparison(op), Instruction_::CmpOp(op, _, _) => OpCode::Comparison(op),
Instruction_::ConvOp{operation, ..} => OpCode::Conversion(operation),
Instruction_::AtomicRMW{op, ..} => OpCode::AtomicRMW(op), Instruction_::AtomicRMW{op, ..} => OpCode::AtomicRMW(op),
Instruction_::ExprCall{..} => OpCode::ExprCall, Instruction_::ExprCall{..} => OpCode::ExprCall,
Instruction_::Load{..} => OpCode::Load, Instruction_::Load{..} => OpCode::Load,
......
...@@ -12,6 +12,14 @@ lazy_static! { ...@@ -12,6 +12,14 @@ lazy_static! {
pub static ref ADDRESS_TYPE : P<MuType> = P( pub static ref ADDRESS_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::int(POINTER_SIZE * 8)) 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( pub static ref UINT32_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::int(32)) MuType::new(new_internal_id(), MuType_::int(32))
...@@ -27,6 +35,8 @@ lazy_static! { ...@@ -27,6 +35,8 @@ lazy_static! {
pub static ref INTERNAL_TYPES : Vec<P<MuType>> = vec![ pub static ref INTERNAL_TYPES : Vec<P<MuType>> = vec![
ADDRESS_TYPE.clone(), ADDRESS_TYPE.clone(),
UINT8_TYPE.clone(),
UINT16_TYPE.clone(),
UINT32_TYPE.clone(), UINT32_TYPE.clone(),
UINT64_TYPE.clone(), UINT64_TYPE.clone(),
DOUBLE_TYPE.clone() DOUBLE_TYPE.clone()
......
...@@ -625,7 +625,7 @@ impl ASMInst { ...@@ -625,7 +625,7 @@ impl ASMInst {
} }
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq, Eq)]
struct ASMLocation { struct ASMLocation {
line: usize, line: usize,
index: usize, index: usize,
...@@ -1062,22 +1062,335 @@ impl ASMCodeGen { ...@@ -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
)
}
}
}