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/* **/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,6 +63,7 @@ testjit:milestones: ...@@ -63,6 +63,7 @@ testjit:milestones:
dependencies: dependencies:
- build_test - build_test
script: script:
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo build 2>/dev/null
- RUST_BACKTRACE=1 pytest tests/test_jit/test_milestones.py - RUST_BACKTRACE=1 pytest tests/test_jit/test_milestones.py
testjit:binops: testjit:binops:
...@@ -70,6 +71,7 @@ testjit:binops: ...@@ -70,6 +71,7 @@ testjit:binops:
dependencies: dependencies:
- build_test - build_test
script: script:
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo build 2>/dev/null
- RUST_BACKTRACE=1 pytest tests/test_jit/test_binops.py - RUST_BACKTRACE=1 pytest tests/test_jit/test_binops.py
testjit:cmpops: testjit:cmpops:
...@@ -77,4 +79,11 @@ testjit:cmpops: ...@@ -77,4 +79,11 @@ testjit:cmpops:
dependencies: dependencies:
- build_test - build_test
script: script:
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo build 2>/dev/null
- RUST_BACKTRACE=1 pytest tests/test_jit/test_cmpops.py - 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,
......
...@@ -13,6 +13,14 @@ lazy_static! { ...@@ -13,6 +13,14 @@ lazy_static! {
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,12 +1062,325 @@ impl ASMCodeGen { ...@@ -1062,12 +1062,325 @@ 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