From b12737c0c3c48cdf39570616eb0401c098451d4c Mon Sep 17 00:00:00 2001 From: qinsoon Date: Tue, 21 Feb 2017 14:43:37 +1100 Subject: [PATCH] use setbyte to implement comparison as value, added a few tests --- .../backend/arch/x86_64/asm_backend.rs | 110 ++++++++---------- src/compiler/backend/arch/x86_64/codegen.rs | 11 ++ src/compiler/backend/arch/x86_64/inst_sel.rs | 53 ++++----- src/gc/src/objectmodel/mod.rs | 2 + tests/test_compiler/test_mem_inst.rs | 109 +++++++++++++++++ 5 files changed, 194 insertions(+), 91 deletions(-) diff --git a/src/compiler/backend/arch/x86_64/asm_backend.rs b/src/compiler/backend/arch/x86_64/asm_backend.rs index 6c2a8989..da8a9ac2 100644 --- a/src/compiler/backend/arch/x86_64/asm_backend.rs +++ b/src/compiler/backend/arch/x86_64/asm_backend.rs @@ -1175,6 +1175,23 @@ impl ASMCodeGen { self.cur.take().unwrap() } + fn internal_uniop_def_r(&mut self, inst: &str, op: &P) { + trace!("emit: {} {}", inst, op); + + let (reg, id, loc) = self.prepare_reg(op, inst.len() + 1); + + let asm = format!("{} {}", inst, reg); + + self.add_asm_inst( + asm, + linked_hashmap!{ + id => vec![loc] + }, + linked_hashmap!{}, + false + ) + } + fn internal_binop_no_def_r_r(&mut self, inst: &str, op1: &P, op2: &P) { let len = check_op_len(op1); @@ -1892,71 +1909,46 @@ impl CodeGenerator for ASMCodeGen { // set byte fn emit_sets_r8(&mut self, dest: Reg) { - trace!("emit: sets {}", dest); - - let (reg, id, loc) = self.prepare_reg(dest, 4 + 1); - - let asm = format!("sets {}", reg); - - self.add_asm_inst( - asm, - linked_hashmap!{ - id => vec![loc] - }, - linked_hashmap!{}, - false - ) + self.internal_uniop_def_r("sets", dest) } - fn emit_setz_r8(&mut self, dest: Reg) { - trace!("emit: setz {}", dest); - - let (reg, id, loc) = self.prepare_reg(dest, 4 + 1); - - let asm = format!("setz {}", reg); - - self.add_asm_inst( - asm, - linked_hashmap!{ - id => vec![loc] - }, - linked_hashmap!{}, - false - ) + self.internal_uniop_def_r("setz", dest) } - fn emit_seto_r8(&mut self, dest: Reg) { - trace!("emit: seto {}", dest); - - let (reg, id, loc) = self.prepare_reg(dest, 4 + 1); - - let asm = format!("seto {}", reg); - - self.add_asm_inst( - asm, - linked_hashmap!{ - id => vec![loc] - }, - linked_hashmap!{}, - false - ) + self.internal_uniop_def_r("seto", dest) } - fn emit_setb_r8(&mut self, dest: Reg) { - trace!("emit: setb {}", dest); - - let (reg, id, loc) = self.prepare_reg(dest, 4 + 1); - - let asm = format!("setb {}", reg); - - self.add_asm_inst( - asm, - linked_hashmap!{ - id => vec![loc] - }, - linked_hashmap!{}, - false - ) + self.internal_uniop_def_r("setb", dest) + } + fn emit_seta_r (&mut self, dest: Reg) { + self.internal_uniop_def_r("seta", dest) + } + fn emit_setae_r (&mut self, dest: Reg) { + self.internal_uniop_def_r("setae", dest) + } + fn emit_setb_r (&mut self, dest: Reg) { + self.internal_uniop_def_r("setb", dest) + } + fn emit_setbe_r (&mut self, dest: Reg) { + self.internal_uniop_def_r("setbe", dest) + } + fn emit_sete_r (&mut self, dest: Reg) { + self.internal_uniop_def_r("sete", dest) + } + fn emit_setg_r (&mut self, dest: Reg) { + self.internal_uniop_def_r("setg", dest) + } + fn emit_setge_r (&mut self, dest: Reg) { + self.internal_uniop_def_r("setge", dest) + } + fn emit_setl_r (&mut self, dest: Reg) { + self.internal_uniop_def_r("setl", dest) + } + fn emit_setle_r (&mut self, dest: Reg) { + self.internal_uniop_def_r("setle", dest) + } + fn emit_setne_r (&mut self, dest: Reg) { + self.internal_uniop_def_r("setne", dest) } // cmov src -> dest diff --git a/src/compiler/backend/arch/x86_64/codegen.rs b/src/compiler/backend/arch/x86_64/codegen.rs index 6bd49afe..6aa45359 100644 --- a/src/compiler/backend/arch/x86_64/codegen.rs +++ b/src/compiler/backend/arch/x86_64/codegen.rs @@ -54,6 +54,17 @@ pub trait CodeGenerator { fn emit_seto_r8 (&mut self, dest: Reg); fn emit_setb_r8 (&mut self, dest: Reg); + fn emit_seta_r (&mut self, dest: Reg); + fn emit_setae_r (&mut self, dest: Reg); + fn emit_setb_r (&mut self, dest: Reg); + fn emit_setbe_r (&mut self, dest: Reg); + fn emit_sete_r (&mut self, dest: Reg); + fn emit_setg_r (&mut self, dest: Reg); + fn emit_setge_r (&mut self, dest: Reg); + fn emit_setl_r (&mut self, dest: Reg); + fn emit_setle_r (&mut self, dest: Reg); + fn emit_setne_r (&mut self, dest: Reg); + // gpr conditional move fn emit_cmova_r_r (&mut self, dest: Reg, src: Reg); diff --git a/src/compiler/backend/arch/x86_64/inst_sel.rs b/src/compiler/backend/arch/x86_64/inst_sel.rs index e9e4528c..5ca227d6 100644 --- a/src/compiler/backend/arch/x86_64/inst_sel.rs +++ b/src/compiler/backend/arch/x86_64/inst_sel.rs @@ -431,43 +431,32 @@ impl <'a> InstructionSelection { let ref op2 = ops[op2]; let tmp_res = self.get_result_value(node); + + debug_assert!(tmp_res.ty.get_int_length().is_some()); + debug_assert!(tmp_res.ty.get_int_length().unwrap() == 1); - // cmov only take (16/32/64bits registers) - // so we use 64bits registers here and truncate later - - // make res64, and set to zero - let tmp_res64 = self.make_temporary(f_context, UINT64_TYPE.clone(), vm); - self.backend.emit_xor_r_r(&tmp_res64, &tmp_res64); - - // set tmp1 as 1 (cmov doesnt allow immediate or reg8 as operand) - let tmp_1 = self.make_temporary(f_context, UINT64_TYPE.clone(), vm); - self.backend.emit_mov_r_imm(&tmp_1, 1); - - // cmov 1 to result + // set byte to result match self.emit_cmp_res(node, f_content, f_context, vm) { - EQ => self.backend.emit_cmove_r_r (&tmp_res64, &tmp_1), - NE => self.backend.emit_cmovne_r_r(&tmp_res64, &tmp_1), - SGE => self.backend.emit_cmovge_r_r(&tmp_res64, &tmp_1), - SGT => self.backend.emit_cmovg_r_r (&tmp_res64, &tmp_1), - SLE => self.backend.emit_cmovle_r_r(&tmp_res64, &tmp_1), - SLT => self.backend.emit_cmovl_r_r (&tmp_res64, &tmp_1), - UGE => self.backend.emit_cmovae_r_r(&tmp_res64, &tmp_1), - UGT => self.backend.emit_cmova_r_r (&tmp_res64, &tmp_1), - ULE => self.backend.emit_cmovbe_r_r(&tmp_res64, &tmp_1), - ULT => self.backend.emit_cmovb_r_r (&tmp_res64, &tmp_1), - - FOEQ | FUEQ => self.backend.emit_cmove_r_r (&tmp_res64, &tmp_1), - FONE | FUNE => self.backend.emit_cmovne_r_r(&tmp_res64, &tmp_1), - FOGT | FUGT => self.backend.emit_cmova_r_r (&tmp_res64, &tmp_1), - FOGE | FUGE => self.backend.emit_cmovae_r_r(&tmp_res64, &tmp_1), - FOLT | FULT => self.backend.emit_cmovb_r_r (&tmp_res64, &tmp_1), - FOLE | FULE => self.backend.emit_cmovbe_r_r(&tmp_res64, &tmp_1), + EQ => self.backend.emit_sete_r (&tmp_res), + NE => self.backend.emit_setne_r(&tmp_res), + SGE => self.backend.emit_setge_r(&tmp_res), + SGT => self.backend.emit_setg_r (&tmp_res), + SLE => self.backend.emit_setle_r(&tmp_res), + SLT => self.backend.emit_setl_r (&tmp_res), + UGE => self.backend.emit_setae_r(&tmp_res), + UGT => self.backend.emit_seta_r (&tmp_res), + ULE => self.backend.emit_setbe_r(&tmp_res), + ULT => self.backend.emit_setb_r (&tmp_res), + + FOEQ | FUEQ => self.backend.emit_sete_r (&tmp_res), + FONE | FUNE => self.backend.emit_setne_r(&tmp_res), + FOGT | FUGT => self.backend.emit_seta_r (&tmp_res), + FOGE | FUGE => self.backend.emit_setae_r(&tmp_res), + FOLT | FULT => self.backend.emit_setb_r (&tmp_res), + FOLE | FULE => self.backend.emit_setbe_r(&tmp_res), _ => unimplemented!() } - - // truncate tmp_res64 to tmp_res (probably u8) - self.backend.emit_mov_r_r(&tmp_res, unsafe {&tmp_res64.as_type(UINT8_TYPE.clone())}); } Instruction_::Branch1(ref dest) => { diff --git a/src/gc/src/objectmodel/mod.rs b/src/gc/src/objectmodel/mod.rs index b8d6342b..4f1877e4 100644 --- a/src/gc/src/objectmodel/mod.rs +++ b/src/gc/src/objectmodel/mod.rs @@ -49,6 +49,8 @@ pub use self::sidemap::MINIMAL_ALIGNMENT; #[cfg(feature = "use-sidemap")] pub use self::sidemap::OBJECT_HEADER_SIZE; #[cfg(feature = "use-sidemap")] +pub use self::sidemap::OBJECT_HEADER_OFFSET; +#[cfg(feature = "use-sidemap")] pub use self::sidemap::REF_BITS_LEN; #[cfg(feature = "use-sidemap")] pub use self::sidemap::OBJ_START_BIT; diff --git a/tests/test_compiler/test_mem_inst.rs b/tests/test_compiler/test_mem_inst.rs index 6044e951..28e5082a 100644 --- a/tests/test_compiler/test_mem_inst.rs +++ b/tests/test_compiler/test_mem_inst.rs @@ -1,17 +1,126 @@ +extern crate libloading; + use mu::ast::types::*; use mu::ast::ir::*; use mu::ast::inst::*; use mu::ast::op::*; use mu::vm::*; use mu::compiler::*; +use mu::runtime::mm::objectmodel::OBJECT_HEADER_OFFSET; use mu::utils::LinkedHashMap; use std::sync::Arc; use std::sync::RwLock; use mu::testutil::aot; +use mu::testutil; use test_compiler::test_call::gen_ccall_exit; +#[test] +fn test_get_field_iref1() { + let lib = testutil::compile_fnc("get_field_iref1", &get_field_iref1); + + unsafe { + let get_field_iref1 : libloading::Symbol u64> = lib.get(b"get_field_iref1").unwrap(); + + let addr = 0x10000000; + let res = get_field_iref1(addr); + println!("get_field_iref1({}) = {}", addr, res); + + assert!(addr + 8 == res); + } +} + +fn get_field_iref1() -> VM { + let vm = VM::new(); + + typedef! ((vm) int64 = mu_int(64)); + typedef! ((vm) ref_int64 = mu_ref(int64)); + typedef! ((vm) iref_int64 = mu_iref(int64)); + typedef! ((vm) mystruct = mu_struct(int64, int64, ref_int64)); + typedef! ((vm) ref_mystruct = mu_ref(mystruct)); + typedef! ((vm) iref_mystruct = mu_iref(mystruct)); + + funcsig! ((vm) sig = (ref_mystruct) -> (iref_int64)); + funcdecl! ((vm) get_field_iref1); + + funcdef! ((vm) get_field_iref1 VERSION get_field_iref1_v1); + + block! ((vm, get_field_iref1_v1) blk_entry); + ssa! ((vm, get_field_iref1_v1) x); + + ssa! ((vm, get_field_iref1_v1) x_); + inst! ((vm, get_field_iref1_v1) blk_entry_get_iref: + x_ = GETIREF x + ); + + ssa! ((vm, get_field_iref1_v1) ret); + inst! ((vm, get_field_iref1_v1) blk_entry_get_field_iref1: + ret = GETFIELDIREF x_ (is_ptr: false, index: 1) + ); + + inst! ((vm, get_field_iref1_v1) blk_entry_ret: + RET (ret) + ); + + + define_block! ((vm, get_field_iref1_v1) blk_entry(x) { + blk_entry_get_iref, blk_entry_get_field_iref1, blk_entry_ret + }); + + define_func_ver!((vm) get_field_iref1_v1 (entry: blk_entry) {blk_entry}); + + vm +} + +#[test] +fn test_get_iref() { + let lib = testutil::compile_fnc("get_iref", &get_iref); + + unsafe { + let get_iref : libloading::Symbol u64> = lib.get(b"get_iref").unwrap(); + + let addr = 0x10000000; + let res = get_iref(addr); + println!("get_iref({}) = {}", addr, res); + + assert!(addr == res); + } +} + +fn get_iref() -> VM { + let vm = VM::new(); + + typedef! ((vm) int64 = mu_int(64)); + typedef! ((vm) ref_int64 = mu_ref(int64)); + typedef! ((vm) iref_int64 = mu_iref(int64)); + + funcsig! ((vm) sig = (ref_int64) -> (iref_int64)); + funcdecl! ((vm) get_iref); + + funcdef! ((vm) get_iref VERSION get_iref_v1); + + block! ((vm, get_iref_v1) blk_entry); + ssa! ((vm, get_iref_v1) x); + + ssa! ((vm, get_iref_v1) ret); + inst! ((vm, get_iref_v1) blk_entry_get_iref: + ret = GETIREF x + ); + + inst! ((vm, get_iref_v1) blk_entry_ret: + RET (ret) + ); + + define_block! ((vm, get_iref_v1) blk_entry(x) { + blk_entry_get_iref, blk_entry_ret + }); + + define_func_ver!((vm) get_iref_v1 (entry: blk_entry) {blk_entry}); + + vm +} + #[test] fn test_struct() { VM::start_logging_trace(); -- 2.21.0