Commit 967d053f authored by qinsoon's avatar qinsoon

[wip] CmpOp as value. Going to massive redesign/refactor the code.

currently we only use 64bit registers, extend/truncate result if it is
not 64bits. This is awful. Going to use all the registers, for example,
AL, AX, EAX, RAX, but will not use AH (so reg alloc is simpler)
parent 6c06ffd1
...@@ -583,25 +583,16 @@ impl Value { ...@@ -583,25 +583,16 @@ impl Value {
pub fn is_int_const(&self) -> bool { pub fn is_int_const(&self) -> bool {
match self.v { match self.v {
Value_::Constant(_) => { Value_::Constant(Constant::Int(_)) => true,
let ty : &MuType = &self.ty; Value_::Constant(Constant::NullRef) => true,
match ty.v {
MuType_::Int(_) => true,
_ => false
}
}
_ => false _ => false
} }
} }
pub fn extract_int_const(&self) -> u64 { pub fn extract_int_const(&self) -> u64 {
match self.v { match self.v {
Value_::Constant(ref c) => { Value_::Constant(Constant::Int(val)) => val,
match c { Value_::Constant(Constant::NullRef) => 0,
&Constant::Int(val) => val,
_ => panic!("expect int const")
}
},
_ => panic!("expect int const") _ => panic!("expect int const")
} }
} }
......
...@@ -13,6 +13,10 @@ lazy_static! { ...@@ -13,6 +13,10 @@ 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 UINT1_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::int(1))
);
pub static ref UINT8_TYPE : P<MuType> = P( pub static ref UINT8_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::int(8)) MuType::new(new_internal_id(), MuType_::int(8))
); );
......
...@@ -1119,7 +1119,7 @@ fn op_postfix(op_len: usize) -> &'static str { ...@@ -1119,7 +1119,7 @@ fn op_postfix(op_len: usize) -> &'static str {
} }
// general instruction emission // general instruction emission
macro_rules! binop_no_def_r_r { macro_rules! cmp_r_r {
($func_name: ident, $inst: expr, $op_len: expr) => { ($func_name: ident, $inst: expr, $op_len: expr) => {
fn $func_name (&mut self, op1: &P<Value>, op2: &P<Value>) { fn $func_name (&mut self, op1: &P<Value>, op2: &P<Value>) {
// with postfix // with postfix
...@@ -1134,9 +1134,17 @@ macro_rules! binop_no_def_r_r { ...@@ -1134,9 +1134,17 @@ macro_rules! binop_no_def_r_r {
self.add_asm_inst( self.add_asm_inst(
asm, asm,
hashmap!{}, hashmap!{},
hashmap!{ {
id1 => vec![loc1], if id1 == id2 {
id2 => vec![loc2] hashmap!{
id1 => vec![loc1, loc2]
}
} else {
hashmap!{
id1 => vec![loc1],
id2 => vec![loc2]
}
}
}, },
false false
) )
...@@ -1144,7 +1152,7 @@ macro_rules! binop_no_def_r_r { ...@@ -1144,7 +1152,7 @@ macro_rules! binop_no_def_r_r {
} }
} }
macro_rules! binop_no_def_imm_r { macro_rules! cmp_imm_r {
($func_name: ident, $inst: expr, $op_len: expr, $imm_ty: ty) => { ($func_name: ident, $inst: expr, $op_len: expr, $imm_ty: ty) => {
fn $func_name (&mut self, op1: $imm_ty, op2: &P<Value>) { fn $func_name (&mut self, op1: $imm_ty, op2: &P<Value>) {
let inst = $inst.to_string() + &op_postfix($op_len); let inst = $inst.to_string() + &op_postfix($op_len);
...@@ -1167,7 +1175,7 @@ macro_rules! binop_no_def_imm_r { ...@@ -1167,7 +1175,7 @@ macro_rules! binop_no_def_imm_r {
} }
} }
macro_rules! binop_no_def_mem_r { macro_rules! cmp_mem_r {
($func_name: ident, $inst:expr, $op_len: expr) => { ($func_name: ident, $inst:expr, $op_len: expr) => {
fn $func_name (&mut self, op1: &P<Value>, op2: &P<Value>) { fn $func_name (&mut self, op1: &P<Value>, op2: &P<Value>) {
let inst = $inst.to_string() + &op_postfix($op_len); let inst = $inst.to_string() + &op_postfix($op_len);
...@@ -1212,9 +1220,17 @@ macro_rules! binop_def_r_r { ...@@ -1212,9 +1220,17 @@ macro_rules! binop_def_r_r {
hashmap!{ hashmap!{
id2 => vec![loc2.clone()] id2 => vec![loc2.clone()]
}, },
hashmap!{ {
id1 => vec![loc1], if id1 == id2 {
id2 => vec![loc2] hashmap!{
id1 => vec![loc1, loc2]
}
} else {
hashmap!{
id1 => vec![loc1],
id2 => vec![loc2]
}
}
}, },
false false
) )
...@@ -1398,6 +1414,89 @@ macro_rules! mov_mem_imm { ...@@ -1398,6 +1414,89 @@ macro_rules! mov_mem_imm {
} }
} }
/// conditional move
macro_rules! binop_no_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!{},
{
if id1 == id2 {
hashmap!{
id1 => vec![loc1, loc2]
}
} else {
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, 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!{},
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, 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!{},
uses,
true
)
}
}
}
macro_rules! emit_lea_r { macro_rules! emit_lea_r {
($func_name: ident, $op_len: expr) => { ($func_name: ident, $op_len: expr) => {
fn $func_name (&mut self, dest: &P<Value>, src: &P<Value>) { fn $func_name (&mut self, dest: &P<Value>, src: &P<Value>) {
...@@ -1613,20 +1712,20 @@ impl CodeGenerator for ASMCodeGen { ...@@ -1613,20 +1712,20 @@ impl CodeGenerator for ASMCodeGen {
} }
// cmp // cmp
binop_no_def_r_r!(emit_cmp_r64_r64, "cmp", 64); cmp_r_r!(emit_cmp_r64_r64, "cmp", 64);
binop_no_def_r_r!(emit_cmp_r32_r32, "cmp", 32); cmp_r_r!(emit_cmp_r32_r32, "cmp", 32);
binop_no_def_r_r!(emit_cmp_r16_r16, "cmp", 16); cmp_r_r!(emit_cmp_r16_r16, "cmp", 16);
binop_no_def_r_r!(emit_cmp_r8_r8 , "cmp", 8 ); cmp_r_r!(emit_cmp_r8_r8 , "cmp", 8 );
binop_no_def_imm_r!(emit_cmp_imm32_r64, "cmp", 64, i32); cmp_imm_r!(emit_cmp_imm32_r64, "cmp", 64, i32);
binop_no_def_imm_r!(emit_cmp_imm32_r32, "cmp", 32, i32); cmp_imm_r!(emit_cmp_imm32_r32, "cmp", 32, i32);
binop_no_def_imm_r!(emit_cmp_imm16_r16, "cmp", 16, i16); cmp_imm_r!(emit_cmp_imm16_r16, "cmp", 16, i16);
binop_no_def_imm_r!(emit_cmp_imm8_r8 , "cmp", 8 , i8 ); cmp_imm_r!(emit_cmp_imm8_r8 , "cmp", 8 , i8 );
binop_no_def_mem_r!(emit_cmp_mem64_r64, "cmp", 64); cmp_mem_r!(emit_cmp_mem64_r64, "cmp", 64);
binop_no_def_mem_r!(emit_cmp_mem32_r32, "cmp", 32); cmp_mem_r!(emit_cmp_mem32_r32, "cmp", 32);
binop_no_def_mem_r!(emit_cmp_mem16_r16, "cmp", 16); cmp_mem_r!(emit_cmp_mem16_r16, "cmp", 16);
binop_no_def_mem_r!(emit_cmp_mem8_r8 , "cmp", 8 ); cmp_mem_r!(emit_cmp_mem8_r8 , "cmp", 8 );
// mov // mov
...@@ -1659,45 +1758,35 @@ impl CodeGenerator for ASMCodeGen { ...@@ -1659,45 +1758,35 @@ impl CodeGenerator for ASMCodeGen {
// cmov // cmov
mov_r_r!(emit_cmova_r64_r64, "cmova", 64); binop_no_def_r_r! (emit_cmova_r64_r64, "cmova", 64);
mov_r_imm!(emit_cmova_r64_imm32, "cmova", 64, i32); binop_no_def_r_mem!(emit_cmova_r64_mem64, "cmova", 64);
mov_r_mem!(emit_cmova_r64_mem64, "cmova", 64);
mov_r_r!(emit_cmovae_r64_r64, "cmovae", 64); binop_no_def_r_r! (emit_cmovae_r64_r64, "cmovae", 64);
mov_r_imm!(emit_cmovae_r64_imm32, "cmovae", 64, i32); binop_no_def_r_mem!(emit_cmovae_r64_mem64,"cmovae", 64);
mov_r_mem!(emit_cmovae_r64_mem64, "cmovae", 64);
mov_r_r!(emit_cmovb_r64_r64, "cmovb", 64); binop_no_def_r_r! (emit_cmovb_r64_r64, "cmovb", 64);
mov_r_imm!(emit_cmovb_r64_imm32, "cmovb", 64, i32); binop_no_def_r_mem!(emit_cmovb_r64_mem64, "cmovb", 64);
mov_r_mem!(emit_cmovb_r64_mem64, "cmovb", 64);
mov_r_r!(emit_cmovbe_r64_r64, "cmovbe", 64); binop_no_def_r_r! (emit_cmovbe_r64_r64, "cmovbe", 64);
mov_r_imm!(emit_cmovbe_r64_imm32, "cmovbe", 64, i32); binop_no_def_r_mem!(emit_cmovbe_r64_mem64,"cmovbe", 64);
mov_r_mem!(emit_cmovbe_r64_mem64, "cmovbe", 64);
mov_r_r!(emit_cmove_r64_r64, "cmove", 64); binop_no_def_r_r! (emit_cmove_r64_r64, "cmove", 64);
mov_r_imm!(emit_cmove_r64_imm32, "cmove", 64, i32); binop_no_def_r_mem!(emit_cmove_r64_mem64, "cmove", 64);
mov_r_mem!(emit_cmove_r64_mem64, "cmove", 64);
mov_r_r!(emit_cmovne_r64_r64, "cmovne", 64); binop_no_def_r_r! (emit_cmovne_r64_r64, "cmovne", 64);
mov_r_imm!(emit_cmovne_r64_imm32, "cmovne", 64, i32); binop_no_def_r_mem!(emit_cmovne_r64_mem64,"cmovne", 64);
mov_r_mem!(emit_cmovne_r64_mem64, "cmovne", 64);
mov_r_r!(emit_cmovg_r64_r64, "cmovg", 64); binop_no_def_r_r! (emit_cmovg_r64_r64, "cmovg", 64);
mov_r_imm!(emit_cmovg_r64_imm32, "cmovg", 64, i32); binop_no_def_r_mem!(emit_cmovg_r64_mem64, "cmovg", 64);
mov_r_mem!(emit_cmovg_r64_mem64, "cmovg", 64);
mov_r_r!(emit_cmovge_r64_r64, "cmovge", 64); binop_no_def_r_r! (emit_cmovge_r64_r64, "cmovge", 64);
mov_r_imm!(emit_cmovge_r64_imm32, "cmovge", 64, i32); binop_no_def_r_mem!(emit_cmovge_r64_mem64,"cmovge", 64);
mov_r_mem!(emit_cmovge_r64_mem64, "cmovge", 64);
mov_r_r!(emit_cmovl_r64_r64, "cmovl", 64); binop_no_def_r_r! (emit_cmovl_r64_r64, "cmovl", 64);
mov_r_imm!(emit_cmovl_r64_imm32, "cmovl", 64, i32); binop_no_def_r_mem!(emit_cmovl_r64_mem64, "cmovl", 64);
mov_r_mem!(emit_cmovl_r64_mem64, "cmovl", 64);
mov_r_r!(emit_cmovle_r64_r64, "cmovle", 64); binop_no_def_r_r! (emit_cmovle_r64_r64, "cmovle", 64);
mov_r_imm!(emit_cmovle_r64_imm32, "cmovle", 64, i32); binop_no_def_r_mem!(emit_cmovle_r64_mem64,"cmovle", 64);
mov_r_mem!(emit_cmovle_r64_mem64, "cmovle", 64);
// lea // lea
mov_r_mem!(emit_lea_r64, "lea", 64); mov_r_mem!(emit_lea_r64, "lea", 64);
...@@ -1718,6 +1807,11 @@ impl CodeGenerator for ASMCodeGen { ...@@ -1718,6 +1807,11 @@ impl CodeGenerator for ASMCodeGen {
binop_def_r_mem!(emit_and_r16_mem16, "and", 16); binop_def_r_mem!(emit_and_r16_mem16, "and", 16);
binop_def_r_mem!(emit_and_r8_mem8 , "and", 8 ); binop_def_r_mem!(emit_and_r8_mem8 , "and", 8 );
// or
binop_def_r_r! (emit_or_r64_r64, "or", 64);
binop_def_r_imm!(emit_or_r64_imm32, "or", 64, i32);
binop_def_r_mem!(emit_or_r64_mem64, "or", 64);
// xor // xor
binop_def_r_r!(emit_xor_r64_r64, "xor", 64); binop_def_r_r!(emit_xor_r64_r64, "xor", 64);
binop_def_r_r!(emit_xor_r32_r32, "xor", 32); binop_def_r_r!(emit_xor_r32_r32, "xor", 32);
......
...@@ -76,43 +76,33 @@ pub trait CodeGenerator { ...@@ -76,43 +76,33 @@ pub trait CodeGenerator {
// gpr conditional move // gpr conditional move
fn emit_cmova_r64_r64 (&mut self, dest: Reg, src: Reg); fn emit_cmova_r64_r64 (&mut self, dest: Reg, src: Reg);
fn emit_cmova_r64_imm32(&mut self, dest: Reg, src: i32);
fn emit_cmova_r64_mem64(&mut self, dest: Reg, src: Mem); // load fn emit_cmova_r64_mem64(&mut self, dest: Reg, src: Mem); // load
fn emit_cmovae_r64_r64 (&mut self, dest: Reg, src: Reg); fn emit_cmovae_r64_r64 (&mut self, dest: Reg, src: Reg);
fn emit_cmovae_r64_imm32(&mut self, dest: Reg, src: i32);
fn emit_cmovae_r64_mem64(&mut self, dest: Reg, src: Mem); // load fn emit_cmovae_r64_mem64(&mut self, dest: Reg, src: Mem); // load
fn emit_cmovb_r64_r64 (&mut self, dest: Reg, src: Reg); fn emit_cmovb_r64_r64 (&mut self, dest: Reg, src: Reg);
fn emit_cmovb_r64_imm32(&mut self, dest: Reg, src: i32);
fn emit_cmovb_r64_mem64(&mut self, dest: Reg, src: Mem); // load fn emit_cmovb_r64_mem64(&mut self, dest: Reg, src: Mem); // load
fn emit_cmovbe_r64_r64 (&mut self, dest: Reg, src: Reg); fn emit_cmovbe_r64_r64 (&mut self, dest: Reg, src: Reg);
fn emit_cmovbe_r64_imm32(&mut self, dest: Reg, src: i32);
fn emit_cmovbe_r64_mem64(&mut self, dest: Reg, src: Mem); // load fn emit_cmovbe_r64_mem64(&mut self, dest: Reg, src: Mem); // load
fn emit_cmove_r64_r64 (&mut self, dest: Reg, src: Reg); fn emit_cmove_r64_r64 (&mut self, dest: Reg, src: Reg);
fn emit_cmove_r64_imm32(&mut self, dest: Reg, src: i32);
fn emit_cmove_r64_mem64(&mut self, dest: Reg, src: Mem); // load fn emit_cmove_r64_mem64(&mut self, dest: Reg, src: Mem); // load
fn emit_cmovg_r64_r64 (&mut self, dest: Reg, src: Reg); fn emit_cmovg_r64_r64 (&mut self, dest: Reg, src: Reg);
fn emit_cmovg_r64_imm32(&mut self, dest: Reg, src: i32);
fn emit_cmovg_r64_mem64(&mut self, dest: Reg, src: Mem); // load fn emit_cmovg_r64_mem64(&mut self, dest: Reg, src: Mem); // load
fn emit_cmovge_r64_r64 (&mut self, dest: Reg, src: Reg); fn emit_cmovge_r64_r64 (&mut self, dest: Reg, src: Reg);
fn emit_cmovge_r64_imm32(&mut self, dest: Reg, src: i32);
fn emit_cmovge_r64_mem64(&mut self, dest: Reg, src: Mem); // load fn emit_cmovge_r64_mem64(&mut self, dest: Reg, src: Mem); // load
fn emit_cmovl_r64_r64 (&mut self, dest: Reg, src: Reg); fn emit_cmovl_r64_r64 (&mut self, dest: Reg, src: Reg);
fn emit_cmovl_r64_imm32(&mut self, dest: Reg, src: i32);
fn emit_cmovl_r64_mem64(&mut self, dest: Reg, src: Mem); // load fn emit_cmovl_r64_mem64(&mut self, dest: Reg, src: Mem); // load
fn emit_cmovle_r64_r64 (&mut self, dest: Reg, src: Reg); fn emit_cmovle_r64_r64 (&mut self, dest: Reg, src: Reg);
fn emit_cmovle_r64_imm32(&mut self, dest: Reg, src: i32);
fn emit_cmovle_r64_mem64(&mut self, dest: Reg, src: Mem); // load fn emit_cmovle_r64_mem64(&mut self, dest: Reg, src: Mem); // load
fn emit_cmovne_r64_r64 (&mut self, dest: Reg, src: Reg); fn emit_cmovne_r64_r64 (&mut self, dest: Reg, src: Reg);
fn emit_cmovne_r64_imm32(&mut self, dest: Reg, src: i32);
fn emit_cmovne_r64_mem64(&mut self, dest: Reg, src: Mem); // load fn emit_cmovne_r64_mem64(&mut self, dest: Reg, src: Mem); // load
// lea // lea
...@@ -168,6 +158,11 @@ pub trait CodeGenerator { ...@@ -168,6 +158,11 @@ pub trait CodeGenerator {
fn emit_add_r8_r8 (&mut self, dest: Reg, src: Reg); fn emit_add_r8_r8 (&mut self, dest: Reg, src: Reg);
fn emit_add_r8_mem8(&mut self, dest: Reg, src: Mem); fn emit_add_r8_mem8(&mut self, dest: Reg, src: Mem);
fn emit_add_r8_imm8(&mut self, dest: Reg, src: i8); fn emit_add_r8_imm8(&mut self, dest: Reg, src: i8);
// or
fn emit_or_r64_r64 (&mut self, dest: Reg, src: Reg);
fn emit_or_r64_imm32(&mut self, dest: Reg, src: i32);
fn emit_or_r64_mem64(&mut self, dest: Reg, src: Mem);
// sub // sub
fn emit_sub_r64_r64 (&mut self, dest: Reg, src: Reg); fn emit_sub_r64_r64 (&mut self, dest: Reg, src: Reg);
......
...@@ -182,6 +182,7 @@ impl RegGroup { ...@@ -182,6 +182,7 @@ impl RegGroup {
pub fn get(ty: &P<MuType>) -> RegGroup { pub fn get(ty: &P<MuType>) -> RegGroup {
match ty.v { match ty.v {
// for now, only use 64bits registers // for now, only use 64bits registers
MuType_::Int(len) if len == 1 => RegGroup::GPR,
MuType_::Int(len) if len == 8 => RegGroup::GPR, MuType_::Int(len) if len == 8 => RegGroup::GPR,
MuType_::Int(len) if len == 16 => RegGroup::GPR, MuType_::Int(len) if len == 16 => RegGroup::GPR,
MuType_::Int(len) if len == 32 => RegGroup::GPR, MuType_::Int(len) if len == 32 => RegGroup::GPR,
......
...@@ -175,6 +175,21 @@ macro_rules! inst { ...@@ -175,6 +175,21 @@ macro_rules! inst {
}); });
}; };
// CONVOP
(($vm: expr, $fv: ident) $name: ident: $value: ident = CONVOP ($operation: expr) <$ty1: ident $ty2: ident> $operand: ident) => {
let $name = $fv.new_inst(Instruction{
hdr: MuEntityHeader::unnamed($vm.next_id()),
value: Some(vec![$value.clone_value()]),
ops: RwLock::new(vec![$operand.clone()]),
v: Instruction_::ConvOp{
operation: $operation,
from_ty: $ty1.clone(),
to_ty: $ty2.clone(),
operand: 0
}
});
};
// SELECT // SELECT
(($vm: expr, $fv: ident) $name: ident: $value: ident = SELECT $cond: ident $op_true: ident $op_false:ident) => { (($vm: expr, $fv: ident) $name: ident: $value: ident = SELECT $cond: ident $op_true: ident $op_false:ident) => {
let $name = $fv.new_inst(Instruction{ let $name = $fv.new_inst(Instruction{
......
...@@ -322,5 +322,129 @@ fn select_sge_zero() -> VM { ...@@ -322,5 +322,129 @@ fn select_sge_zero() -> VM {
define_func_ver!((vm) select_v1 (entry: blk_entry) {blk_entry}); define_func_ver!((vm) select_v1 (entry: blk_entry) {blk_entry});
vm
}
#[test]
fn test_sgt_value() {
let lib = testutil::compile_fnc("sgt_value", &sgt_value);
unsafe {
let sgt_value : libloading::Symbol<unsafe extern fn(i64, i64) -> u64> = lib.get(b"sgt_value").unwrap();
let res = sgt_value(255, 0);
println!("sgt_value(255, 0) = {}", res);
assert!(res == 1);
let res = sgt_value(255, 255);
println!("sgt_value(255, 255) = {}", res);
assert!(res == 0);
let res = sgt_value(0, 255);
println!("sgt_value(0, 255) = {}", res);
assert!(res == 0);
}
}
fn sgt_value() -> VM {
let vm = VM::new();
typedef! ((vm) int64 = mu_int(64));
typedef! ((vm) int1 = mu_int(1));
constdef!((vm) <int64> int64_0 = Constant::Int(0));
constdef!((vm) <int64> int64_1 = Constant::Int(1));
funcsig! ((vm) sig = (int64, int64) -> (int1));
funcdecl!((vm) <sig> sgt_value);
funcdef! ((vm) <sig> sgt_value VERSION sgt_value_v1);
// blk entry
block! ((vm, sgt_value_v1) blk_entry);
ssa! ((vm, sgt_value_v1) <int64> blk_entry_op1);
ssa! ((vm, sgt_value_v1) <int64> blk_entry_op2);
ssa! ((vm, sgt_value_v1) <int1> blk_entry_cond);
inst! ((vm, sgt_value_v1) blk_entry_inst_cmp:
blk_entry_cond = CMPOP (CmpOp::SGT) blk_entry_op1 blk_entry_op2
);
inst! ((vm, sgt_value_v1) blk_entry_inst_ret:
RET (blk_entry_cond)
);
define_block! ((vm, sgt_value_v1) blk_entry(blk_entry_op1, blk_entry_op2){
blk_entry_inst_cmp, blk_entry_inst_ret
});
define_func_ver!((vm) sgt_value_v1 (entry: blk_entry) {blk_entry});
vm
}
#[test]
fn test_sgt_u8_value() {
let lib = testutil::compile_fnc("sgt_u8_value", &sgt_u8_value);
unsafe {
let sgt_u8_value : libloading::Symbol<unsafe extern fn(i8, i8) -> u64> = lib.get(b"sgt_u8_value").unwrap();
let res = sgt_u8_value(-1, 0);
println!("sgt_u8_value(-1, 0) = {}", res);
assert!(res == 0);
let res = sgt_u8_value(0, -1);
println!("sgt_u8_value(0, -1) = {}", res);
assert!(res == 1);
let res = sgt_u8_value(2, 1);
println!("sgt_u8_value(2, 1) = {}", res);
assert!(res == 1);
let res = sgt_u8_value(1, 2);
println!("sgt_u8_value(1, 2) = {}", res);
assert!(res == 0);
let res = sgt_u8_value(-2, -1);
println!("sgt_u8_value(-2, -1) = {}", res);
assert!(res == 0);
let res = sgt_u8_value(-1, -2);
println!("sgt_u8_value(-1, -2) = {}", res);
assert!(res == 1);
}
}
fn sgt_u8_value() -> VM {
let vm = VM::new();
typedef! ((vm) int8 = mu_int(8));
typedef! ((vm) int1 = mu_int(1));
constdef!((vm) <int8> int8_0 = Constant::Int(0));
constdef!((vm) <int8> int8_1 = Constant::Int(1));
funcsig! ((vm) sig = (int8, int8) -> (int1));
funcdecl!((vm) <sig> sgt_u8_value);
funcdef! ((vm) <sig> sgt_u8_value VERSION sgt_u8_value_v1);
// blk entry
block! ((vm, sgt_u8_value_v1) blk_entry);
ssa! ((vm, sgt_u8_value_v1) <int8> blk_entry_op1);
ssa! ((vm, sgt_u8_value_v1) <int8> blk_entry_op2);
ssa! ((vm, sgt_u8_value_v1) <int1> blk_entry_cond);
inst! ((vm, sgt_u8_value_v1) blk_entry_inst_cmp:
blk_entry_cond = CMPOP (CmpOp::SGT) blk_entry_op1 blk_entry_op2
);
inst! ((vm, sgt_u8_value_v1) blk_entry_inst_ret:
RET (blk_entry_cond)
);
define_block! ((vm, sgt_u8_value_v1) blk_entry(blk_entry_op1, blk_entry_op2){
blk_entry_inst_cmp, blk_entry_inst_ret
});
define_func_ver!((vm) sgt_u8_value_v1 (entry: blk_entry) {blk_entry});
vm vm
} }
\ No newline at end of file
...@@ -110,89 +110,37 @@ fn test_truncate() { ...@@ -110,89 +110,37 @@ fn test_truncate() {
fn truncate() -> VM { fn truncate() -> VM {
let vm = VM::new(); let vm = VM::new();
// .typedef @u64 = int<64> typedef! ((vm) u64 = mu_int(64));
let type_def_u64 = vm.declare_type(vm.next_id(), MuType_::int(64)); typedef! ((vm) u8 = mu_int(8));
vm.set_name(type_def_u64.as_entity(), Mu("u64"));
// .typedef @u64 = int<8> funcsig! ((vm) sig = (u64) -> (u64));
let type_def_u64 = vm.declare_type(vm.next_id(), MuType_::int(8)); funcdecl!((vm) <sig> truncate);
vm.set_name(type_def_u64.as_entity(), Mu("u64")); funcdef! ((vm) <sig> truncate VERSION truncate_v1);
// .funcsig @truncate_sig = (@u64) -> (@u64) block! ((vm, trucnate_v1) blk_entry);
let truncate_sig = vm.declare_func_sig(vm.next_id(), vec![type_def_u64.clone()], vec![type_def_u64.clone()]); ssa! ((vm, truncate_v1) <u64> blk_entry_a);
vm.set_name(truncate_sig.as_entity(), Mu("truncate_sig"));
ssa! ((vm, truncate_v1) <u8> blk_entry_r);
// .funcdecl @truncate <@truncate_sig> inst! ((vm, truncate_v1) blk_entry_truncate:
let func_id = vm.next_id(); blk_entry_r = CONVOP (ConvOp::TRUNC) <u64 u8> blk_entry_a
let func = MuFunction::new(func_id, truncate_sig.clone()); );
vm.set_name(func.as_entity(), Mu("truncate"));
vm.declare_func(func); ssa! ((vm, truncate_v1) <u64> blk_entry_r2);
inst! ((vm, truncate_v1) blk_entry_zext:
// .funcdef @truncate VERSION @truncate_v1 <@truncate_sig> blk_entry_r2 = CONVOP (ConvOp::ZEXT) <u8 u64> blk_entry_r
let mut func_ver = MuFunctionVersion::new(vm.next_id(), func_id, truncate_sig.clone()); );
vm.set_name(func_ver.as_entity(), Mu("truncate_v1"));
inst! ((vm, truncate_v1) blk_entry_ret:
// %entry(<@u64> %a): RET (blk_entry_r2)