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
Pipeline #335 passed with stage
in 57 minutes and 12 seconds
......@@ -588,7 +588,7 @@ impl BlockContent {
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")
......
......@@ -1693,9 +1693,7 @@ impl ASMCodeGen {
}
}
fn internal_mov_mem_imm(&mut self, inst: &str, dest: &P<Value>, src: i32) {
let len = check_op_len(dest);
fn internal_mov_mem_imm(&mut self, inst: &str, dest: &P<Value>, src: i32, len: usize) {
let inst = inst.to_string() + &op_postfix(len);
trace!("emit: {} {} -> {}", inst, src, dest);
......@@ -2132,8 +2130,8 @@ impl CodeGenerator for ASMCodeGen {
fn emit_mov_mem_r (&mut self, dest: &P<Value>, src: &P<Value>) {
self.internal_mov_mem_r("mov", dest, src, false)
}
fn emit_mov_mem_imm(&mut self, dest: &P<Value>, src: i32) {
self.internal_mov_mem_imm("mov", dest, src)
fn emit_mov_mem_imm(&mut self, dest: &P<Value>, src: i32, oplen: usize) {
self.internal_mov_mem_imm("mov", dest, src, oplen)
}
// zero/sign extend mov
......
......@@ -50,7 +50,9 @@ pub trait CodeGenerator {
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_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
fn emit_movs_r_r (&mut self, dest: Reg, src: Reg);
......
......@@ -908,9 +908,9 @@ impl <'a> InstructionSelection {
let resolved_loc = self.emit_node_addr_to_value(loc_op, f_content, f_context, vm);
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 {
self.backend.emit_mov_mem_imm(&resolved_loc, val);
self.backend.emit_mov_mem_imm(&resolved_loc, val, len);
} else {
unimplemented!()
}
......@@ -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> {
match op.v {
TreeNode_::Value(ref pv) => {
......@@ -3033,11 +3040,21 @@ impl <'a> InstructionSelection {
}
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 {
Value_::Constant(Constant::Int(val)) => {
debug_assert!(x86_64::is_valid_x86_imm(op));
val as i32
(val as i32, op_length)
},
_ => panic!("expected iimm")
}
......@@ -3518,11 +3535,11 @@ impl <'a> InstructionSelection {
if !types::is_fp(dst_ty) && types::is_scalar(dst_ty) {
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() {
self.backend.emit_mov_r_imm(dest, src_imm);
} 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 {
panic!("unexpected dest: {}", dest);
}
......@@ -3559,8 +3576,8 @@ impl <'a> InstructionSelection {
} else if dest.is_mem() && src.is_int_reg() {
self.backend.emit_mov_mem_r(dest, src);
} else if dest.is_mem() && src.is_int_const() {
let imm = self.value_iimm_to_i32(src);
self.backend.emit_mov_mem_imm(dest, imm);
let (imm, len) = self.value_iimm_to_i32_with_len(src);
self.backend.emit_mov_mem_imm(dest, imm, len);
} else {
panic!("unexpected gpr mov between {} -> {}", src, dest);
}
......
......@@ -15,6 +15,153 @@ use mu::testutil;
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]
fn test_get_field_iref1() {
let lib = testutil::compile_fnc("get_field_iref1", &get_field_iref1);
......
......@@ -1149,7 +1149,6 @@ def test_linked_list():
assert res.out == '1\n'
@may_spawn_proc
@pytest.mark.xfail(reason='segment fault')
def test_rpytarget_richards():
from rpython.translator.goal.richards import entry_point
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