Commit 364ece82 authored by qinsoon's avatar qinsoon

[wip] implementing most operations for float type

parent db99809f
...@@ -37,6 +37,10 @@ lazy_static! { ...@@ -37,6 +37,10 @@ lazy_static! {
MuType::new(new_internal_id(), MuType_::double()) MuType::new(new_internal_id(), MuType_::double())
); );
pub static ref FLOAT_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::float())
);
pub static ref VOID_TYPE : P<MuType> = P( pub static ref VOID_TYPE : P<MuType> = P(
MuType::new(new_internal_id(), MuType_::void()) MuType::new(new_internal_id(), MuType_::void())
); );
...@@ -49,6 +53,7 @@ lazy_static! { ...@@ -49,6 +53,7 @@ lazy_static! {
UINT32_TYPE.clone(), UINT32_TYPE.clone(),
UINT64_TYPE.clone(), UINT64_TYPE.clone(),
DOUBLE_TYPE.clone(), DOUBLE_TYPE.clone(),
FLOAT_TYPE.clone(),
VOID_TYPE.clone() VOID_TYPE.clone()
]; ];
} }
...@@ -179,6 +184,20 @@ impl MuType { ...@@ -179,6 +184,20 @@ impl MuType {
_ => None _ => None
} }
} }
pub fn is_float(&self) -> bool {
match self.v {
MuType_::Float => true,
_ => false
}
}
pub fn is_double(&self) -> bool {
match self.v {
MuType_::Double => true,
_ => false
}
}
} }
pub type StructTag = MuName; pub type StructTag = MuName;
......
...@@ -1710,6 +1710,26 @@ impl ASMCodeGen { ...@@ -1710,6 +1710,26 @@ impl ASMCodeGen {
) )
} }
fn internal_fp_mov_f_f(&mut self, inst: &str, dest: Reg, src: Reg) {
trace!("emit: {} {} -> {}", inst, src, dest);
let (reg1, id1, loc1) = self.prepare_fpreg(src, inst.len() + 1);
let (reg2, id2, loc2) = self.prepare_fpreg(dest, inst.len() + 1 + reg1.len() + 1);
let asm = format!("{} {},{}", inst, reg1, reg2);
self.add_asm_inst(
asm,
linked_hashmap!{
id2 => vec![loc2]
},
linked_hashmap!{
id1 => vec![loc1]
},
false
)
}
fn internal_fp_mov_f_mem(&mut self, inst: &str, dest: Reg, src: Mem, fn internal_fp_mov_f_mem(&mut self, inst: &str, dest: Reg, src: Mem,
is_spill_related: bool is_spill_related: bool
) { ) {
...@@ -1837,6 +1857,52 @@ impl ASMCodeGen { ...@@ -1837,6 +1857,52 @@ impl ASMCodeGen {
unimplemented!() unimplemented!()
} }
fn internal_gpr_to_fpr(&mut self, inst: &str, dest: Reg, src: Reg) {
let len = check_op_len(src);
let inst = inst.to_string() + &op_postfix(len);
trace!("emit: {} {} -> {}", inst, src, dest);
let (reg1, id1, loc1) = self.prepare_reg(src, inst.len() + 1);
let (reg2, id2, loc2) = self.prepare_fpreg(dest, inst.len() + 1 + reg1.len() + 1);
let asm = format!("{} {}, {}", inst, reg1, reg2);
self.add_asm_inst(
asm,
linked_hashmap!{
id2 => vec![loc2]
},
linked_hashmap!{
id1 => vec![loc1]
},
false
)
}
fn internal_fpr_to_gpr(&mut self, inst: &str, dest: Reg, src: Reg) {
let len = check_op_len(dest);
let inst = inst.to_string() + &op_postfix(len);
trace!("emit: {} {} -> {}", inst, src, dest);
let (reg1, id1, loc1) = self.prepare_fpreg(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,
linked_hashmap!{
id2 => vec![loc2]
},
linked_hashmap!{
id1 => vec![loc1]
},
false
)
}
fn emit_spill_store_gpr(&mut self, dest: Mem, src: Reg) { fn emit_spill_store_gpr(&mut self, dest: Mem, src: Reg) {
self.internal_mov_mem_r("mov", dest, src, true) self.internal_mov_mem_r("mov", dest, src, true)
} }
...@@ -2925,36 +2991,36 @@ impl CodeGenerator for ASMCodeGen { ...@@ -2925,36 +2991,36 @@ impl CodeGenerator for ASMCodeGen {
) )
} }
fn emit_movsd_f64_f64 (&mut self, dest: &P<Value>, src: &P<Value>) { // mov - double
trace!("emit: movsd {} -> {}", src, dest);
let (reg1, id1, loc1) = self.prepare_fpreg(src, 5 + 1);
let (reg2, id2, loc2) = self.prepare_fpreg(dest, 5 + 1 + reg1.len() + 1);
let asm = format!("movsd {},{}", reg1, reg2); fn emit_movsd_f64_f64 (&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_mov_f_f("movsd", dest, src)
self.add_asm_inst(
asm,
linked_hashmap!{
id2 => vec![loc2]
},
linked_hashmap!{
id1 => vec![loc1]
},
false
)
} }
// load // load
fn emit_movsd_f64_mem64(&mut self, dest: &P<Value>, src: &P<Value>) { fn emit_movsd_f64_mem64(&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_mov_f_mem("movsd", dest, src, false) self.internal_fp_mov_f_mem("movsd", dest, src, false)
} }
// store // store
fn emit_movsd_mem64_f64(&mut self, dest: &P<Value>, src: &P<Value>) { fn emit_movsd_mem64_f64(&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_mov_mem_f("movsd", dest, src, false) self.internal_fp_mov_mem_f("movsd", dest, src, false)
} }
// mov - float
fn emit_movss_f32_f32 (&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_mov_f_f("movss", dest, src)
}
// load
fn emit_movss_f32_mem32(&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_mov_f_mem("movss", dest, src, false)
}
// store
fn emit_movss_mem32_f32(&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_mov_mem_f("movss", dest, src, false)
}
// compare - double
fn emit_comisd_f64_f64 (&mut self, op1: Reg, op2: Reg) { fn emit_comisd_f64_f64 (&mut self, op1: Reg, op2: Reg) {
self.internal_fp_binop_no_def_r_r("comisd", op1, op2); self.internal_fp_binop_no_def_r_r("comisd", op1, op2);
} }
...@@ -2962,14 +3028,35 @@ impl CodeGenerator for ASMCodeGen { ...@@ -2962,14 +3028,35 @@ impl CodeGenerator for ASMCodeGen {
self.internal_fp_binop_no_def_r_r("ucomisd", op1, op2); self.internal_fp_binop_no_def_r_r("ucomisd", op1, op2);
} }
// compare - float
fn emit_comiss_f32_f32 (&mut self, op1: Reg, op2: Reg) {
self.internal_fp_binop_no_def_r_r("comiss", op1, op2);
}
fn emit_ucomiss_f32_f32 (&mut self, op1: Reg, op2: Reg) {
self.internal_fp_binop_no_def_r_r("ucomiss", op1, op2);
}
// add - double
fn emit_addsd_f64_f64 (&mut self, dest: &P<Value>, src: &P<Value>) { fn emit_addsd_f64_f64 (&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_binop_def_r_r("addsd", dest, src); self.internal_fp_binop_def_r_r("addsd", dest, src);
} }
fn emit_addsd_f64_mem64(&mut self, dest: &P<Value>, src: &P<Value>) { fn emit_addsd_f64_mem64(&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_binop_def_r_mem("addsd", dest, src); self.internal_fp_binop_def_r_mem("addsd", dest, src);
} }
// add - float
fn emit_addss_f32_f32 (&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_binop_def_r_r("addss", dest, src);
}
fn emit_addss_f32_mem32(&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_fp_binop_def_r_mem("addss", dest, src);
}
// sub - double
fn emit_subsd_f64_f64 (&mut self, dest: Reg, src: Reg) { fn emit_subsd_f64_f64 (&mut self, dest: Reg, src: Reg) {
self.internal_fp_binop_def_r_r("subsd", dest, src); self.internal_fp_binop_def_r_r("subsd", dest, src);
} }
...@@ -2977,6 +3064,17 @@ impl CodeGenerator for ASMCodeGen { ...@@ -2977,6 +3064,17 @@ impl CodeGenerator for ASMCodeGen {
self.internal_fp_binop_def_r_mem("subsd", dest, src); self.internal_fp_binop_def_r_mem("subsd", dest, src);
} }
// sub - float
fn emit_subss_f32_f32 (&mut self, dest: Reg, src: Reg) {
self.internal_fp_binop_def_r_r("subss", dest, src);
}
fn emit_subss_f32_mem32(&mut self, dest: Reg, src: Mem) {
self.internal_fp_binop_def_r_mem("subss", dest, src);
}
// div - double
fn emit_divsd_f64_f64 (&mut self, dest: Reg, src: Reg) { fn emit_divsd_f64_f64 (&mut self, dest: Reg, src: Reg) {
self.internal_fp_binop_def_r_r("divsd", dest, src); self.internal_fp_binop_def_r_r("divsd", dest, src);
} }
...@@ -2984,6 +3082,17 @@ impl CodeGenerator for ASMCodeGen { ...@@ -2984,6 +3082,17 @@ impl CodeGenerator for ASMCodeGen {
self.internal_fp_binop_def_r_mem("divsd", dest, src); self.internal_fp_binop_def_r_mem("divsd", dest, src);
} }
// div - float
fn emit_divss_f32_f32 (&mut self, dest: Reg, src: Reg) {
self.internal_fp_binop_def_r_r("divss", dest, src);
}
fn emit_divss_f32_mem32(&mut self, dest: Reg, src: Mem) {
self.internal_fp_binop_def_r_mem("divss", dest, src);
}
// mul - double
fn emit_mulsd_f64_f64 (&mut self, dest: Reg, src: Reg) { fn emit_mulsd_f64_f64 (&mut self, dest: Reg, src: Reg) {
self.internal_fp_binop_def_r_r("mulsd", dest, src); self.internal_fp_binop_def_r_r("mulsd", dest, src);
} }
...@@ -2991,50 +3100,31 @@ impl CodeGenerator for ASMCodeGen { ...@@ -2991,50 +3100,31 @@ impl CodeGenerator for ASMCodeGen {
self.internal_fp_binop_def_r_mem("mulsd", dest, src); self.internal_fp_binop_def_r_mem("mulsd", dest, src);
} }
fn emit_cvtsi2sd_f64_r (&mut self, dest: Reg, src: Reg) { // mul - float
let len = check_op_len(src);
let inst = "cvtsi2sd".to_string() + &op_postfix(len); fn emit_mulss_f32_f32 (&mut self, dest: Reg, src: Reg) {
trace!("emit: {} {} -> {}", inst, src, dest); self.internal_fp_binop_def_r_r("mulss", dest, src);
}
let (reg1, id1, loc1) = self.prepare_reg (src, inst.len() + 1); fn emit_mulss_f32_mem32(&mut self, dest: Reg, src: Mem) {
let (reg2, id2, loc2) = self.prepare_fpreg(dest, inst.len() + 1 + reg1.len() + 1); self.internal_fp_binop_def_r_mem("mulss", dest, src);
}
let asm = format!("{} {},{}", inst, reg1, reg2); // convert - double
self.add_asm_inst( fn emit_cvtsi2sd_f64_r (&mut self, dest: Reg, src: Reg) {
asm, self.internal_gpr_to_fpr("cvtsi2sd", dest, src);
linked_hashmap!{
id2 => vec![loc2]
},
linked_hashmap!{
id1 => vec![loc1]
},
false
)
} }
fn emit_cvtsd2si_r_f64 (&mut self, dest: Reg, src: Reg) { fn emit_cvtsd2si_r_f64 (&mut self, dest: Reg, src: Reg) {
let len = check_op_len(dest); self.internal_fpr_to_gpr("cvtsd2si", dest, src);
}
let inst = "cvtsd2si".to_string() + &op_postfix(len);
trace!("emit: {} {} -> {}", inst, src, dest);
let (reg1, id1, loc1) = self.prepare_fpreg(src, inst.len() + 1);
let (reg2, id2, loc2) = self.prepare_reg (dest, inst.len() + 1 + reg1.len() + 1);
let asm = format!("{} {},{}", inst, reg1, reg2); // convert - single
self.add_asm_inst( fn emit_cvtsi2ss_f32_r (&mut self, dest: Reg, src: Reg) {
asm, self.internal_gpr_to_fpr("cvtsi2ss", dest, src);
linked_hashmap!{ }
id2 => vec![loc2] fn emit_cvtss2si_r_f32 (&mut self, dest: Reg, src: Reg) {
}, self.internal_fpr_to_gpr("cvtss2si", dest, src);
linked_hashmap!{
id1 => vec![loc1]
},
false
)
} }
// unpack low data - interleave low byte // unpack low data - interleave low byte
......
...@@ -188,33 +188,56 @@ pub trait CodeGenerator { ...@@ -188,33 +188,56 @@ pub trait CodeGenerator {
fn emit_movsd_f64_mem64(&mut self, dest: &P<Value>, src: &P<Value>); // load fn emit_movsd_f64_mem64(&mut self, dest: &P<Value>, src: &P<Value>); // load
fn emit_movsd_mem64_f64(&mut self, dest: &P<Value>, src: &P<Value>); // store fn emit_movsd_mem64_f64(&mut self, dest: &P<Value>, src: &P<Value>); // store
fn emit_movss_f32_f32 (&mut self, dest: &P<Value>, src: &P<Value>);
fn emit_movss_f32_mem32(&mut self, dest: &P<Value>, src: &P<Value>); // load
fn emit_movss_mem32_f32(&mut self, dest: &P<Value>, src: &P<Value>); // store
// fp add // fp add
fn emit_addsd_f64_f64 (&mut self, dest: Reg, src: Reg); fn emit_addsd_f64_f64 (&mut self, dest: Reg, src: Reg);
fn emit_addsd_f64_mem64(&mut self, dest: Reg, src: Mem); fn emit_addsd_f64_mem64(&mut self, dest: Reg, src: Mem);
fn emit_addss_f32_f32 (&mut self, dest: Reg, src: Reg);
fn emit_addss_f32_mem32(&mut self, dest: Reg, src: Mem);
// fp sub // fp sub
fn emit_subsd_f64_f64 (&mut self, dest: Reg, src: Reg); fn emit_subsd_f64_f64 (&mut self, dest: Reg, src: Reg);
fn emit_subsd_f64_mem64(&mut self, dest: Reg, src: Mem); fn emit_subsd_f64_mem64(&mut self, dest: Reg, src: Mem);
fn emit_subss_f32_f32 (&mut self, dest: Reg, src: Reg);
fn emit_subss_f32_mem32(&mut self, dest: Reg, src: Mem);
// fp div // fp div
fn emit_divsd_f64_f64 (&mut self, dest: Reg, src: Reg); fn emit_divsd_f64_f64 (&mut self, dest: Reg, src: Reg);
fn emit_divsd_f64_mem64(&mut self, dest: Reg, src: Mem); fn emit_divsd_f64_mem64(&mut self, dest: Reg, src: Mem);
fn emit_divss_f32_f32 (&mut self, dest: Reg, src: Reg);
fn emit_divss_f32_mem32(&mut self, dest: Reg, src: Mem);
// fp mul // fp mul
fn emit_mulsd_f64_f64 (&mut self, dest: Reg, src: Reg); fn emit_mulsd_f64_f64 (&mut self, dest: Reg, src: Reg);
fn emit_mulsd_f64_mem64(&mut self, dest: Reg, src: Mem); fn emit_mulsd_f64_mem64(&mut self, dest: Reg, src: Mem);
fn emit_mulss_f32_f32 (&mut self, dest: Reg, src: Reg);
fn emit_mulss_f32_mem32(&mut self, dest: Reg, src: Mem);
// fp comparison // fp comparison
fn emit_comisd_f64_f64 (&mut self, op1: Reg, op2: Reg); fn emit_comisd_f64_f64 (&mut self, op1: Reg, op2: Reg);
fn emit_ucomisd_f64_f64 (&mut self, op1: Reg, op2: Reg); fn emit_ucomisd_f64_f64 (&mut self, op1: Reg, op2: Reg);
fn emit_comiss_f32_f32 (&mut self, op1: Reg, op2: Reg);
fn emit_ucomiss_f32_f32 (&mut self, op1: Reg, op2: Reg);
// fp conversion // fp conversion
fn emit_cvtsi2sd_f64_r (&mut self, dest: Reg, src: Reg); fn emit_cvtsi2sd_f64_r (&mut self, dest: Reg, src: Reg);
fn emit_cvtsd2si_r_f64 (&mut self, dest: Reg, src: Reg); fn emit_cvtsd2si_r_f64 (&mut self, dest: Reg, src: Reg);
fn emit_cvttsd2si_r_f64 (&mut self, dest: Reg, src: Reg);
fn emit_cvtsi2ss_f32_r (&mut self, dest: Reg, src: Reg);
fn emit_cvtss2si_r_f32 (&mut self, dest: Reg, src: Reg);
// used for unsigned int to fp conversion // used for unsigned int to fp conversion
fn emit_cvttsd2si_r_f64 (&mut self, dest: Reg, src: Reg);
// unpack low data - interleave low byte // unpack low data - interleave low byte
fn emit_punpckldq_f64_mem128(&mut self, dest: Reg, src: Mem); fn emit_punpckldq_f64_mem128(&mut self, dest: Reg, src: Mem);
// substract packed double-fp // substract packed double-fp
......
...@@ -13,6 +13,7 @@ use compiler::backend::reg_alloc::validate::exact_liveness::*; ...@@ -13,6 +13,7 @@ use compiler::backend::reg_alloc::validate::exact_liveness::*;
const VERIFY_SPILLING : bool = false; const VERIFY_SPILLING : bool = false;
#[allow(unused_variables)]
pub fn validate_regalloc(cf: &CompiledFunction, pub fn validate_regalloc(cf: &CompiledFunction,
reg_assigned: LinkedHashMap<MuID, MuID>, reg_assigned: LinkedHashMap<MuID, MuID>,
spill_scratch_regs: LinkedHashMap<MuID, MuID>) spill_scratch_regs: LinkedHashMap<MuID, MuID>)
......
...@@ -108,13 +108,23 @@ lazy_static! { ...@@ -108,13 +108,23 @@ lazy_static! {
}; };
// impl/decl: math.rs // impl/decl: math.rs
pub static ref FREM : RuntimeEntrypoint = RuntimeEntrypoint { pub static ref FREM_DOUBLE : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig{ sig: P(MuFuncSig{
hdr: MuEntityHeader::unnamed(ir::new_internal_id()), hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![DOUBLE_TYPE.clone()], ret_tys: vec![DOUBLE_TYPE.clone()],
arg_tys: vec![DOUBLE_TYPE.clone(), DOUBLE_TYPE.clone()] arg_tys: vec![DOUBLE_TYPE.clone(), DOUBLE_TYPE.clone()]
}), }),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_frem")), aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_frem_double")),
jit: RwLock::new(None)
};
pub static ref FREM_FLOAT : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig{
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![FLOAT_TYPE.clone()],
arg_tys: vec![FLOAT_TYPE.clone(), FLOAT_TYPE.clone()]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_frem_float")),
jit: RwLock::new(None) jit: RwLock::new(None)
}; };
......
#[no_mangle] #[no_mangle]
#[allow(unreachable_code)] #[allow(unreachable_code)]
pub extern fn muentry_frem(a: f64, b: f64) -> f64 { pub extern fn muentry_frem_double(a: f64, b: f64) -> f64 {
use std::ops::Rem; use std::ops::Rem;
a.rem(b) a.rem(b)
} }
#[no_mangle]
#[allow(unreachable_code)]
pub extern fn muentry_frem_float(a: f32, b: f32) -> f32 {
use std::ops::Rem;
a.rem(b)
}
\ No newline at end of file
...@@ -8,6 +8,10 @@ macro_rules! typedef { ...@@ -8,6 +8,10 @@ macro_rules! typedef {
let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::double()); let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::double());
$vm.set_name($name.as_entity()); $vm.set_name($name.as_entity());
}; };
(($vm: expr) $name: ident = mu_float) => {
let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::float());
$vm.set_name($name.as_entity());
};
// ref, iref, ptr // ref, iref, ptr
(($vm: expr) $name: ident = mu_ref($ty: ident)) => { (($vm: expr) $name: ident = mu_ref($ty: ident)) => {
......
...@@ -13,49 +13,99 @@ use mu::utils::LinkedHashMap; ...@@ -13,49 +13,99 @@ use mu::utils::LinkedHashMap;
use std::sync::RwLock; use std::sync::RwLock;
#[test] #[test]
fn test_fp_add() { fn test_double_add() {
let lib = testutil::compile_fnc("fp_add", &fp_add); let lib = testutil::compile_fnc("double_add", &double_add);
unsafe { unsafe {
let fp_add : libloading::Symbol<unsafe extern fn(f64, f64) -> f64> = lib.get(b"fp_add").unwrap(); let double_add : libloading::Symbol<unsafe extern fn(f64, f64) -> f64> = lib.get(b"double_add").unwrap();
let fp_add_1_1 = fp_add(1f64, 1f64); let double_add_1_1 = double_add(1f64, 1f64);
println!("fp_add(1, 1) = {}", fp_add_1_1); println!("double_add(1, 1) = {}", double_add_1_1);
assert!(fp_add_1_1 == 2f64); assert!(double_add_1_1 == 2f64);
} }
} }
fn fp_add() -> VM { fn double_add() -> VM {
let vm = VM::new(); let vm = VM::new();
typedef! ((vm) double = mu_double); typedef! ((vm) double = mu_double);
funcsig! ((vm) fp_add_sig = (double, double) -> (double)); funcsig! ((vm) double_add_sig = (double, double) -> (double));
funcdecl! ((vm) <fp_add_sig> fp_add); funcdecl! ((vm) <double_add_sig> double_add);
funcdef! ((vm) <fp_add_sig> fp_add VERSION fp_add_v1); funcdef! ((vm) <double_add_sig> double_add VERSION double_add_v1);
// %entry(<@double> %a, <@double> %b): // %entry(<@double> %a, <@double> %b):
block! ((vm, fp_add_v1) blk_entry); block! ((vm, double_add_v1) blk_entry);
ssa! ((vm, fp_add_v1) <double> a); ssa! ((vm, double_add_v1) <double> a);
ssa! ((vm, fp_add_v1) <double> b); ssa! ((vm, double_add_v1) <double> b);
// %r = FADD %a %b // %r = FADD %a %b
ssa! ((vm, fp_add_v1) <double> r); ssa! ((vm, double_add_v1) <double> r);
inst! ((vm, fp_add_v1) blk_entry_fadd: inst! ((vm, double_add_v1) blk_entry_fadd:
r = BINOP (BinOp::FAdd) a b r = BINOP (BinOp::FAdd) a b
); );
// RET %r // RET %r
inst! ((vm, fp_add_v1) blk_entry_ret: inst! ((vm, double_add_v1) blk_entry_ret:
RET (r) RET (r)
); );
define_block! ((vm, fp_add_v1) blk_entry(a, b) { define_block! ((vm, double_add_v1) blk_entry(a, b) {
blk_entry_fadd, blk_entry_fadd,
blk_entry_ret blk_entry_ret
}); });
define_func_ver!((vm) fp_add_v1(entry: blk_entry) { define_func_ver!((vm) double_add_v1(entry: blk_entry) {
blk_entry
});
vm
}
#[test]
fn test_float_add() {
let lib = testutil::compile_fnc("float_add", &float_add);
unsafe {
let float_add : libloading::Symbol<unsafe extern fn(f64, f64) -> f64> = lib.get(b"float_add").unwrap();
let float_add_1_1 = float_add(1f64, 1f64);
println!("float_add(1, 1) = {}", float_add_1_1);
assert!(float_add_1_1 == 2f64);
}
}
fn float_add() -> VM {
let vm = VM::new();
typedef! ((vm) float = mu_float);
funcsig! ((vm) float_add_sig = (float, float) -> (float));
funcdecl! ((vm) <float_add_sig> float_add);
funcdef! ((vm) <float_add_sig> float_add VERSION float_add_v1);
// %entry(<@float> %a, <@float> %b):
block! ((vm, float_add_v1) blk_entry);
ssa! ((vm, float_add_v1) <float> a);
ssa! ((vm, float_add_v1) <float> b);
// %r = FADD %a %b
ssa! ((vm, float_add_v1) <float> r);
inst! ((vm, float_add_v1) blk_entry_fadd:
r = BINOP (BinOp::FAdd) a b
);
// RET %r
inst! ((vm, float_add_v1) blk_entry_ret:
RET (r)
);
define_block! ((vm, float_add_v1) blk_entry(a, b) {
blk_entry_fadd,
blk_entry_ret
});
define_func_ver!((vm) float_add_v1(entry: blk_entry) {
blk_entry blk_entry
}); });
......
Markdown is supported
0% or