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 7e244053 authored by qinsoon's avatar qinsoon
Browse files

branch2 test works fine. milsum runs.

parent 5c3c66af
**/target/*
**/__pycache__/*
**/.cache/*
emit/*
**/emit/*
**/temp/*
Cargo.lock
*.log
......
......@@ -195,8 +195,10 @@ pub struct FunctionContent {
impl fmt::Debug for FunctionContent {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let entry = self.get_entry_block();
write!(f, "Entry block: ").unwrap();
write!(f, "{:?}\n", entry).unwrap();
write!(f, "Body:").unwrap();
for blk_id in self.blocks.keys() {
let block = self.get_block(*blk_id);
write!(f, "{:?}\n", block).unwrap();
......
......@@ -173,6 +173,26 @@ pub enum CmpOp {
FUNO
}
impl CmpOp {
pub fn swap_operands(self) -> CmpOp {
use op::CmpOp::*;
match self {
EQ => EQ,
NE => NE,
SGE => SLT,
SGT => SLE,
SLE => SGT,
SLT => SGE,
UGE => ULT,
UGT => ULE,
ULE => UGT,
ULT => UGE,
_ => unimplemented!()
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub enum ConvOp {
TRUNC,
......
......@@ -1099,21 +1099,21 @@ macro_rules! binop_no_def_r_r {
}
}
macro_rules! binop_no_def_r_imm {
macro_rules! binop_no_def_imm_r {
($func_name: ident, $inst: expr, $op_len: expr, $imm_ty: ty) => {
fn $func_name (&mut self, op1: &P<Value>, op2: $imm_ty) {
fn $func_name (&mut self, op1: $imm_ty, op2: &P<Value>) {
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 (reg2, id2, loc2) = self.prepare_reg(op2, inst.len() + 1 + 1 + op1.to_string().len() + 1);
let asm = format!("{} ${},{}", inst, op2, reg1);
let asm = format!("{} ${},{}", inst, op1, reg2);
self.add_asm_inst(
asm,
hashmap!{},
hashmap!{
id1 => vec![loc1]
id2 => vec![loc2]
},
false
)
......@@ -1122,16 +1122,16 @@ macro_rules! binop_no_def_r_imm {
}
}
macro_rules! binop_no_def_r_mem {
macro_rules! binop_no_def_mem_r {
($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 (mem, mut uses) = self.prepare_mem(op1, inst.len() + 1);
let (reg, id1, loc1) = self.prepare_reg(op2, inst.len() + 1 + mem.len() + 1);
let asm = format!("{} {},{}", inst, reg, mem);
let asm = format!("{} {},{}", inst, mem, reg);
// merge use vec
if uses.contains_key(&id1) {
......@@ -1539,15 +1539,15 @@ impl CodeGenerator for ASMCodeGen {
binop_no_def_r_r!(emit_cmp_r16_r16, "cmp", 16);
binop_no_def_r_r!(emit_cmp_r8_r8 , "cmp", 8 );
binop_no_def_r_imm!(emit_cmp_r64_imm32, "cmp", 64, i32);
binop_no_def_r_imm!(emit_cmp_r32_imm32, "cmp", 32, i32);
binop_no_def_r_imm!(emit_cmp_r16_imm16, "cmp", 16, i16);
binop_no_def_r_imm!(emit_cmp_r8_imm8 , "cmp", 8 , i8 );
binop_no_def_imm_r!(emit_cmp_imm32_r64, "cmp", 64, i32);
binop_no_def_imm_r!(emit_cmp_imm32_r32, "cmp", 32, i32);
binop_no_def_imm_r!(emit_cmp_imm16_r16, "cmp", 16, i16);
binop_no_def_imm_r!(emit_cmp_imm8_r8 , "cmp", 8 , i8 );
binop_no_def_r_mem!(emit_cmp_r64_mem64, "cmp", 64);
binop_no_def_r_mem!(emit_cmp_r32_mem32, "cmp", 32);
binop_no_def_r_mem!(emit_cmp_r16_mem16, "cmp", 16);
binop_no_def_r_mem!(emit_cmp_r8_mem8 , "cmp", 8 );
binop_no_def_mem_r!(emit_cmp_mem64_r64, "cmp", 64);
binop_no_def_mem_r!(emit_cmp_mem32_r32, "cmp", 32);
binop_no_def_mem_r!(emit_cmp_mem16_r16, "cmp", 16);
binop_no_def_mem_r!(emit_cmp_mem8_r8 , "cmp", 8 );
// mov
......
......@@ -27,20 +27,20 @@ pub trait CodeGenerator {
// comparison
fn emit_cmp_r64_r64 (&mut self, op1: Reg, op2: Reg);
fn emit_cmp_r64_imm32(&mut self, op1: Reg, op2: i32);
fn emit_cmp_r64_mem64(&mut self, op1: Reg, op2: Mem);
fn emit_cmp_imm32_r64(&mut self, op1: i32, op2: Reg);
fn emit_cmp_mem64_r64(&mut self, op1: Mem, op2: Reg);
fn emit_cmp_r32_r32 (&mut self, op1: Reg, op2: Reg);
fn emit_cmp_r32_imm32(&mut self, op1: Reg, op2: i32);
fn emit_cmp_r32_mem32(&mut self, op1: Reg, op2: Mem);
fn emit_cmp_imm32_r32(&mut self, op1: i32, op2: Reg);
fn emit_cmp_mem32_r32(&mut self, op1: Mem, op2: Reg);
fn emit_cmp_r16_r16 (&mut self, op1: Reg, op2: Reg);
fn emit_cmp_r16_imm16(&mut self, op1: Reg, op2: i16);
fn emit_cmp_r16_mem16(&mut self, op1: Reg, op2: Mem);
fn emit_cmp_imm16_r16(&mut self, op1: i16, op2: Reg);
fn emit_cmp_mem16_r16(&mut self, op1: Mem, op2: Reg);
fn emit_cmp_r8_r8 (&mut self, op1: Reg, op2: Reg);
fn emit_cmp_r8_imm8 (&mut self, op1: Reg, op2: i8);
fn emit_cmp_r8_mem8 (&mut self, op1: Reg, op2: Mem);
fn emit_cmp_r8_r8 (&mut self, op1: Reg, op2: Reg);
fn emit_cmp_imm8_r8(&mut self, op1: i8, op2: Reg);
fn emit_cmp_mem8_r8(&mut self, op1: Mem, op2: Reg);
// gpr move
......
......@@ -73,8 +73,8 @@ impl <'a> InstructionSelection {
TreeNode_::Instruction(ref inst) => {
match inst.v {
Instruction_::Branch2{cond, ref true_dest, ref false_dest, true_prob} => {
// move this to trace generation
// assert here
// 'branch_if_true' == true, we emit cjmp the same as CmpOp (je for EQ, jne for NE)
// 'branch_if_true' == false, we emit opposite cjmp as CmpOp (jne for EQ, je for NE)
let (fallthrough_dest, branch_dest, branch_if_true) = {
if true_prob > 0.5f32 {
(true_dest, false_dest, false)
......@@ -95,16 +95,76 @@ impl <'a> InstructionSelection {
if self.match_cmp_res(cond) {
trace!("emit cmp_eq-branch2");
match self.emit_cmp_res(cond, f_content, f_context, vm) {
op::CmpOp::EQ => self.backend.emit_je(branch_target),
op::CmpOp::NE => self.backend.emit_jne(branch_target),
op::CmpOp::UGE => self.backend.emit_jae(branch_target),
op::CmpOp::UGT => self.backend.emit_ja(branch_target),
op::CmpOp::ULE => self.backend.emit_jbe(branch_target),
op::CmpOp::ULT => self.backend.emit_jb(branch_target),
op::CmpOp::SGE => self.backend.emit_jge(branch_target),
op::CmpOp::SGT => self.backend.emit_jg(branch_target),
op::CmpOp::SLE => self.backend.emit_jle(branch_target),
op::CmpOp::SLT => self.backend.emit_jl(branch_target),
op::CmpOp::EQ => {
if branch_if_true {
self.backend.emit_je(branch_target);
} else {
self.backend.emit_jne(branch_target);
}
},
op::CmpOp::NE => {
if branch_if_true {
self.backend.emit_jne(branch_target);
} else {
self.backend.emit_je(branch_target);
}
},
op::CmpOp::UGE => {
if branch_if_true {
self.backend.emit_jae(branch_target);
} else {
self.backend.emit_jb(branch_target);
}
},
op::CmpOp::UGT => {
if branch_if_true {
self.backend.emit_ja(branch_target);
} else {
self.backend.emit_jbe(branch_target);
}
},
op::CmpOp::ULE => {
if branch_if_true {
self.backend.emit_jbe(branch_target);
} else {
self.backend.emit_ja(branch_target);
}
},
op::CmpOp::ULT => {
if branch_if_true {
self.backend.emit_jb(branch_target);
} else {
self.backend.emit_jae(branch_target);
}
},
op::CmpOp::SGE => {
if branch_if_true {
self.backend.emit_jge(branch_target);
} else {
self.backend.emit_jl(branch_target);
}
},
op::CmpOp::SGT => {
if branch_if_true {
self.backend.emit_jg(branch_target);
} else {
self.backend.emit_jle(branch_target);
}
},
op::CmpOp::SLE => {
if branch_if_true {
self.backend.emit_jle(branch_target);
} else {
self.backend.emit_jg(branch_target);
}
},
op::CmpOp::SLT => {
if branch_if_true {
self.backend.emit_jl(branch_target);
} else {
self.backend.emit_jge(branch_target);
}
},
_ => unimplemented!()
}
} else if self.match_ireg(cond) {
......@@ -113,9 +173,9 @@ impl <'a> InstructionSelection {
let cond_reg = self.emit_ireg(cond, f_content, f_context, vm);
// emit: cmp cond_reg 1
self.backend.emit_cmp_r64_imm32(&cond_reg, 1);
self.backend.emit_cmp_imm32_r64(1, &cond_reg);
// emit: je #branch_dest
self.backend.emit_je(branch_target);
self.backend.emit_je(branch_target);
} else {
unimplemented!();
}
......@@ -745,12 +805,12 @@ impl <'a> InstructionSelection {
// ASM: cmp %end, [%tl + allocator_offset + limit_offset]
let limit_offset = *thread::ALLOCATOR_OFFSET + *mm::ALLOCATOR_LIMIT_OFFSET;
let mem_limit = self.make_memory_op_base_offset(&tmp_tl, limit_offset as i32, ADDRESS_TYPE.clone(), vm);
self.backend.emit_cmp_r64_mem64(&tmp_end, &mem_limit);
self.backend.emit_cmp_mem64_r64(&mem_limit, &tmp_end);
// branch to slow path if end > limit
// ASM: jl alloc_slow
// branch to slow path if end > limit (end - limit > 0)
// ASM: jg alloc_slow
let slowpath = format!("{}_allocslow", node.id());
self.backend.emit_jl(slowpath.clone());
self.backend.emit_jg(slowpath.clone());
// update cursor
// ASM: mov %end -> [%tl + allocator_offset + cursor_offset]
......@@ -1503,24 +1563,29 @@ impl <'a> InstructionSelection {
let op2 = &ops[op2];
if op::is_int_cmp(op) {
if self.match_ireg(op1) && self.match_ireg(op2) {
let reg_op1 = self.emit_ireg(op1, f_content, f_context, vm);
let reg_op2 = self.emit_ireg(op2, f_content, f_context, vm);
self.backend.emit_cmp_r64_r64(&reg_op1, &reg_op2);
} else if self.match_ireg(op1) && self.match_iimm(op2) {
if self.match_ireg(op1) && self.match_iimm(op2) {
let reg_op1 = self.emit_ireg(op1, f_content, f_context, vm);
let iimm_op2 = self.node_iimm_to_i32(op2);
self.backend.emit_cmp_r64_imm32(&reg_op1, iimm_op2);
// we adopt at&t syntax
// so CMP op1 op2
// is actually CMP op2 op1 (in machine code)
self.backend.emit_cmp_imm32_r64(iimm_op2, &reg_op1);
return op;
} else if self.match_ireg(op1) && self.match_ireg(op2) {
let reg_op1 = self.emit_ireg(op1, f_content, f_context, vm);
let reg_op2 = self.emit_ireg(op2, f_content, f_context, vm);
self.backend.emit_cmp_r64_r64(&reg_op2, &reg_op1);
return op;
} else {
unimplemented!()
}
} else {
unimplemented!()
}
op
}
_ => panic!("expect cmp res to emit")
......@@ -1798,12 +1863,12 @@ impl <'a> InstructionSelection {
let ref dst_ty = dest.ty;
if !types::is_fp(dst_ty) && types::is_scalar(dst_ty) {
if self.match_ireg(src) {
let src_reg = self.emit_ireg(src, f_content, f_context, vm);
self.backend.emit_mov_r64_r64(dest, &src_reg);
} else if self.match_iimm(src) {
if self.match_iimm(src) {
let src_imm = self.node_iimm_to_i32(src);
self.backend.emit_mov_r64_imm32(dest, src_imm);
} else if self.match_ireg(src) {
let src_reg = self.emit_ireg(src, f_content, f_context, vm);
self.backend.emit_mov_r64_r64(dest, &src_reg);
} else {
panic!("expected an int type op");
}
......
......@@ -20,7 +20,9 @@ fn test_sum() {
let lib = testutil::compile_fnc("sum", &sum);
unsafe {
let sumptr: ll::Symbol<unsafe extern fn (u64) -> u64> = lib.get(b"sum").unwrap();
assert!(sumptr(5) == 10);
assert!(sumptr(10) == 45);
println!("sum(5) = {}", sumptr(5));
assert!(sumptr(5) == 15);
println!("sun(10) = {}", sumptr(10));
assert!(sumptr(10) == 55);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment