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 {
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