GitLab will be upgraded to the 12.10.14-ce.0 on 28 Sept 2020 at 2.00pm (AEDT) to 2.30pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

Commit dee3785d authored by qinsoon's avatar qinsoon

emit_mov_mem_imm will take an extra argument for length of the

immiediate number. Richards benchmark runs.
parent ef19bc34
...@@ -588,7 +588,7 @@ impl BlockContent { ...@@ -588,7 +588,7 @@ impl BlockContent {
vec_utils::append_unique(&mut ret, &mut live_outs); vec_utils::append_unique(&mut ret, &mut live_outs);
} }
_ => panic!("didn't expect last inst as {:?}", inst) _ => panic!("didn't expect last inst as {}", inst)
} }
}, },
_ => panic!("expect last treenode of block is a inst") _ => panic!("expect last treenode of block is a inst")
......
...@@ -1693,9 +1693,7 @@ impl ASMCodeGen { ...@@ -1693,9 +1693,7 @@ impl ASMCodeGen {
} }
} }
fn internal_mov_mem_imm(&mut self, inst: &str, dest: &P<Value>, src: i32) { fn internal_mov_mem_imm(&mut self, inst: &str, dest: &P<Value>, src: i32, len: usize) {
let len = check_op_len(dest);
let inst = inst.to_string() + &op_postfix(len); let inst = inst.to_string() + &op_postfix(len);
trace!("emit: {} {} -> {}", inst, src, dest); trace!("emit: {} {} -> {}", inst, src, dest);
...@@ -2132,8 +2130,8 @@ impl CodeGenerator for ASMCodeGen { ...@@ -2132,8 +2130,8 @@ impl CodeGenerator for ASMCodeGen {
fn emit_mov_mem_r (&mut self, dest: &P<Value>, src: &P<Value>) { fn emit_mov_mem_r (&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_mov_mem_r("mov", dest, src, false) self.internal_mov_mem_r("mov", dest, src, false)
} }
fn emit_mov_mem_imm(&mut self, dest: &P<Value>, src: i32) { fn emit_mov_mem_imm(&mut self, dest: &P<Value>, src: i32, oplen: usize) {
self.internal_mov_mem_imm("mov", dest, src) self.internal_mov_mem_imm("mov", dest, src, oplen)
} }
// zero/sign extend mov // zero/sign extend mov
......
...@@ -50,7 +50,9 @@ pub trait CodeGenerator { ...@@ -50,7 +50,9 @@ pub trait CodeGenerator {
fn emit_mov_r_mem (&mut self, dest: Reg, src: Mem); // load fn emit_mov_r_mem (&mut self, dest: Reg, src: Mem); // load
fn emit_mov_r_r (&mut self, dest: Reg, src: Reg); fn emit_mov_r_r (&mut self, dest: Reg, src: Reg);
fn emit_mov_mem_r (&mut self, dest: Mem, src: Reg); // store fn emit_mov_mem_r (&mut self, dest: Mem, src: Reg); // store
fn emit_mov_mem_imm(&mut self, dest: Mem, src: i32); // store // we can infer imm length from Reg, but cannot from Mem
// because mem may only have type as ADDRESS_TYPE
fn emit_mov_mem_imm(&mut self, dest: Mem, src: i32, oplen: usize); // store
// zero/sign extend mov // zero/sign extend mov
fn emit_movs_r_r (&mut self, dest: Reg, src: Reg); fn emit_movs_r_r (&mut self, dest: Reg, src: Reg);
......
...@@ -908,9 +908,9 @@ impl <'a> InstructionSelection { ...@@ -908,9 +908,9 @@ impl <'a> InstructionSelection {
let resolved_loc = self.emit_node_addr_to_value(loc_op, f_content, f_context, vm); let resolved_loc = self.emit_node_addr_to_value(loc_op, f_content, f_context, vm);
if self.match_iimm(val_op) { if self.match_iimm(val_op) {
let val = self.node_iimm_to_i32(val_op); let (val, len) = self.node_iimm_to_i32_with_len(val_op);
if generate_plain_mov { if generate_plain_mov {
self.backend.emit_mov_mem_imm(&resolved_loc, val); self.backend.emit_mov_mem_imm(&resolved_loc, val, len);
} else { } else {
unimplemented!() unimplemented!()
} }
...@@ -3023,6 +3023,13 @@ impl <'a> InstructionSelection { ...@@ -3023,6 +3023,13 @@ impl <'a> InstructionSelection {
} }
} }
fn node_iimm_to_i32_with_len(&mut self, op: &TreeNode) -> (i32, usize) {
match op.v {
TreeNode_::Value(ref pv) => self.value_iimm_to_i32_with_len(pv),
_ => panic!("expected iimm")
}
}
fn node_iimm_to_value(&mut self, op: &TreeNode) -> P<Value> { fn node_iimm_to_value(&mut self, op: &TreeNode) -> P<Value> {
match op.v { match op.v {
TreeNode_::Value(ref pv) => { TreeNode_::Value(ref pv) => {
...@@ -3033,11 +3040,21 @@ impl <'a> InstructionSelection { ...@@ -3033,11 +3040,21 @@ impl <'a> InstructionSelection {
} }
fn value_iimm_to_i32(&mut self, op: &P<Value>) -> i32 { fn value_iimm_to_i32(&mut self, op: &P<Value>) -> i32 {
self.value_iimm_to_i32_with_len(op).0
}
/// also returns the length of the int
fn value_iimm_to_i32_with_len(&mut self, op: &P<Value>) -> (i32, usize) {
let op_length = match op.ty.get_int_length() {
Some(l) => l,
None => panic!("expected an int")
};
match op.v { match op.v {
Value_::Constant(Constant::Int(val)) => { Value_::Constant(Constant::Int(val)) => {
debug_assert!(x86_64::is_valid_x86_imm(op)); debug_assert!(x86_64::is_valid_x86_imm(op));
val as i32 (val as i32, op_length)
}, },
_ => panic!("expected iimm") _ => panic!("expected iimm")
} }
...@@ -3518,11 +3535,11 @@ impl <'a> InstructionSelection { ...@@ -3518,11 +3535,11 @@ impl <'a> InstructionSelection {
if !types::is_fp(dst_ty) && types::is_scalar(dst_ty) { if !types::is_fp(dst_ty) && types::is_scalar(dst_ty) {
if self.match_iimm(src) { if self.match_iimm(src) {
let src_imm = self.node_iimm_to_i32(src); let (src_imm, src_len) = self.node_iimm_to_i32_with_len(src);
if dest.is_int_reg() { if dest.is_int_reg() {
self.backend.emit_mov_r_imm(dest, src_imm); self.backend.emit_mov_r_imm(dest, src_imm);
} else if dest.is_mem() { } else if dest.is_mem() {
self.backend.emit_mov_mem_imm(dest, src_imm); self.backend.emit_mov_mem_imm(dest, src_imm, src_len);
} else { } else {
panic!("unexpected dest: {}", dest); panic!("unexpected dest: {}", dest);
} }
...@@ -3559,8 +3576,8 @@ impl <'a> InstructionSelection { ...@@ -3559,8 +3576,8 @@ impl <'a> InstructionSelection {
} else if dest.is_mem() && src.is_int_reg() { } else if dest.is_mem() && src.is_int_reg() {
self.backend.emit_mov_mem_r(dest, src); self.backend.emit_mov_mem_r(dest, src);
} else if dest.is_mem() && src.is_int_const() { } else if dest.is_mem() && src.is_int_const() {
let imm = self.value_iimm_to_i32(src); let (imm, len) = self.value_iimm_to_i32_with_len(src);
self.backend.emit_mov_mem_imm(dest, imm); self.backend.emit_mov_mem_imm(dest, imm, len);
} else { } else {
panic!("unexpected gpr mov between {} -> {}", src, dest); panic!("unexpected gpr mov between {} -> {}", src, dest);
} }
......
...@@ -15,6 +15,153 @@ use mu::testutil; ...@@ -15,6 +15,153 @@ use mu::testutil;
use test_compiler::test_call::gen_ccall_exit; use test_compiler::test_call::gen_ccall_exit;
#[repr(C)]
struct Foo (i8, i8, i8);
#[test]
fn test_write_int8_val() {
let lib = testutil::compile_fnc("write_int8", &write_int8);
unsafe {
let ptr : *mut Foo = Box::into_raw(Box::new(Foo(1, 2, 3)));
let a = (*ptr).0;
let b = (*ptr).1;
let c = (*ptr).2;
println!("foo.0 = {}", (*ptr).0);
println!("foo.1 = {}", (*ptr).1);
println!("foo.2 = {}", (*ptr).2);
let write_int8 : libloading::Symbol<unsafe extern fn(*mut Foo, i8)> = lib.get(b"write_int8").unwrap();
write_int8(ptr, 42);
println!("foo.0 = {}", (*ptr).0);
println!("foo.1 = {}", (*ptr).1);
println!("foo.2 = {}", (*ptr).2);
assert_eq!((*ptr).0, a);
assert_eq!((*ptr).1, 42);
assert_eq!((*ptr).2, c);
}
}
fn write_int8() -> VM {
let vm = VM::new();
typedef! ((vm) int8 = mu_int(8));
typedef! ((vm) foo = mu_struct(int8, int8, int8));
typedef! ((vm) ref_foo = mu_ref(foo));
typedef! ((vm) iref_foo = mu_iref(foo));
typedef! ((vm) iref_int8 = mu_iref(int8));
funcsig! ((vm) write_int8_sig = (ref_foo, int8) -> ());
funcdecl! ((vm) <write_int8_sig> write_int8);
funcdef! ((vm) <write_int8_sig> write_int8 VERSION write_int8_v1);
block! ((vm, write_int8_v1) blk_entry);
ssa! ((vm, write_int8_v1) <ref_foo> refx);
ssa! ((vm, write_int8_v1) <int8> val);
ssa! ((vm, write_int8_v1) <iref_foo> irefx);
inst! ((vm, write_int8_v1) blk_entry_getiref:
irefx = GETIREF refx
);
ssa! ((vm, write_int8_v1) <iref_int8> iref_field1);
inst! ((vm, write_int8_v1) blk_entry_getfieldiref:
iref_field1 = GETFIELDIREF irefx (is_ptr: false, index: 1)
);
inst! ((vm, write_int8_v1) blk_entry_write:
STORE iref_field1 val (is_ptr: false, order: MemoryOrder::Relaxed)
);
inst! ((vm, write_int8_v1) blk_entry_ret:
RET
);
define_block!((vm, write_int8_v1) blk_entry(refx, val) {
blk_entry_getiref, blk_entry_getfieldiref, blk_entry_write, blk_entry_ret
});
define_func_ver!((vm) write_int8_v1 (entry: blk_entry) {blk_entry});
vm
}
#[test]
fn test_write_int8_const() {
let lib = testutil::compile_fnc("write_int8_const", &write_int8_const);
unsafe {
let ptr : *mut Foo = Box::into_raw(Box::new(Foo(1, 2, 3)));
let a = (*ptr).0;
let b = (*ptr).1;
let c = (*ptr).2;
println!("foo.0 = {}", (*ptr).0);
println!("foo.1 = {}", (*ptr).1);
println!("foo.2 = {}", (*ptr).2);
let write_int8 : libloading::Symbol<unsafe extern fn(*mut Foo)> = lib.get(b"write_int8_const").unwrap();
write_int8(ptr);
println!("foo.0 = {}", (*ptr).0);
println!("foo.1 = {}", (*ptr).1);
println!("foo.2 = {}", (*ptr).2);
assert_eq!((*ptr).0, a);
assert_eq!((*ptr).1, 42);
assert_eq!((*ptr).2, c);
}
}
fn write_int8_const() -> VM {
let vm = VM::new();
typedef! ((vm) int8 = mu_int(8));
typedef! ((vm) foo = mu_struct(int8, int8, int8));
typedef! ((vm) ref_foo = mu_ref(foo));
typedef! ((vm) iref_foo = mu_iref(foo));
typedef! ((vm) iref_int8 = mu_iref(int8));
constdef! ((vm) <int8> int8_42 = Constant::Int(42));
funcsig! ((vm) write_int8_const_sig = (ref_foo) -> ());
funcdecl! ((vm) <write_int8_const_sig> write_int8_const);
funcdef! ((vm) <write_int8_const_sig> write_int8_const VERSION write_int8_const_v1);
block! ((vm, write_int8_const_v1) blk_entry);
ssa! ((vm, write_int8_const_v1) <ref_foo> refx);
ssa! ((vm, write_int8_const_v1) <iref_foo> irefx);
inst! ((vm, write_int8_const_v1) blk_entry_getiref:
irefx = GETIREF refx
);
ssa! ((vm, write_int8_const_v1) <iref_int8> iref_field1);
inst! ((vm, write_int8_const_v1) blk_entry_getfieldiref:
iref_field1 = GETFIELDIREF irefx (is_ptr: false, index: 1)
);
consta! ((vm, write_int8_const_v1) int8_42_local = int8_42);
inst! ((vm, write_int8_const_v1) blk_entry_write:
STORE iref_field1 int8_42_local (is_ptr: false, order: MemoryOrder::Relaxed)
);
inst! ((vm, write_int8_const_v1) blk_entry_ret:
RET
);
define_block!((vm, write_int8_const_v1) blk_entry(refx) {
blk_entry_getiref, blk_entry_getfieldiref, blk_entry_write, blk_entry_ret
});
define_func_ver!((vm) write_int8_const_v1 (entry: blk_entry) {blk_entry});
vm
}
#[test] #[test]
fn test_get_field_iref1() { fn test_get_field_iref1() {
let lib = testutil::compile_fnc("get_field_iref1", &get_field_iref1); let lib = testutil::compile_fnc("get_field_iref1", &get_field_iref1);
......
...@@ -1149,7 +1149,6 @@ def test_linked_list(): ...@@ -1149,7 +1149,6 @@ def test_linked_list():
assert res.out == '1\n' assert res.out == '1\n'
@may_spawn_proc @may_spawn_proc
@pytest.mark.xfail(reason='segment fault')
def test_rpytarget_richards(): def test_rpytarget_richards():
from rpython.translator.goal.richards import entry_point from rpython.translator.goal.richards import entry_point
def main(argv): def main(argv):
......
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