To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

Commit deab5cac authored by qinsoon's avatar qinsoon
Browse files

fix the bug of wrong code sequence emitted for mul

parent 06f9d9a0
......@@ -2672,6 +2672,12 @@ impl<'a> InstructionSelection {
1 | 2 | 4 | 8 => {
trace!("emit mul");
// we need to emit both operands first, then move one into RAX
let tmp_op1 = self.emit_ireg(op1, f_content, f_context, vm);
let tmp_op2 = self.emit_ireg(op2, f_content, f_context, vm);
// move op1 -> RAX
let mreg_op1 = match op_size {
8 => x86_64::RAX.clone(),
4 => x86_64::EAX.clone(),
......@@ -2679,38 +2685,10 @@ impl<'a> InstructionSelection {
1 => x86_64::AL.clone(),
_ => unimplemented!()
};
if self.match_iimm(op1) {
let imm_op1 = self.node_iimm_to_i32(op1);
self.backend.emit_mov_r_imm(&mreg_op1, imm_op1);
} else if self.match_mem(op1) {
let mem_op1 = self.emit_mem(op1, vm);
self.backend.emit_mov_r_mem(&mreg_op1, &mem_op1);
} else if self.match_ireg(op1) {
let reg_op1 = self.emit_ireg(op1, f_content, f_context, vm);
self.backend.emit_mov_r_r(&mreg_op1, &reg_op1);
} else {
panic!("unexpected op1 for node {:?}", node)
}
self.backend.emit_mov_r_r(&mreg_op1, &tmp_op1);
// mul op2
if self.match_iimm(op2) {
let imm_op2 = self.node_iimm_to_i32(op2);
// put imm in a temporary
// here we use result reg as temporary
self.backend.emit_mov_r_imm(&res_tmp, imm_op2);
self.backend.emit_mul_r(&res_tmp);
} else if self.match_mem(op2) {
let mem_op2 = self.emit_mem(op2, vm);
self.backend.emit_mul_mem(&mem_op2);
} else if self.match_ireg(op2) {
let reg_op2 = self.emit_ireg(op2, f_content, f_context, vm);
self.backend.emit_mul_r(&reg_op2);
} else {
panic!("unexpected op2 for node {:?}", node)
}
self.backend.emit_mul_r(&tmp_op2);
// mov rax -> result
let res_size = vm.get_backend_type_size(res_tmp.ty.id());
......
......@@ -650,3 +650,125 @@ fn add_int64_nzc() -> VM {
vm
}
#[test]
fn test_nest_mul_simple() {
VM::start_logging_trace();
let lib = linkutils::aot::compile_fnc("nest_mul_simple", &nest_mul_simple);
unsafe {
let nest_mul_simple: libloading::Symbol<unsafe extern "C" fn(u64, u64, u64) -> u64> =
lib.get(b"nest_mul_simple").unwrap();
let res = nest_mul_simple(2, 3, 4);
println!("mul(2, 3, 4) = {}", res);
assert_eq!(res, 24);
}
}
fn nest_mul_simple() -> VM {
let vm = VM::new();
typedef! ((vm) int64 = mu_int(64));
funcsig! ((vm) sig = (int64, int64, int64) -> (int64));
funcdecl! ((vm) <sig> nest_mul_simple);
funcdef! ((vm) <sig> nest_mul_simple VERSION nest_mul_simple_v1);
// %entry(%x, %y, %z)
block! ((vm, nest_mul_simple_v1) blk_entry);
ssa! ((vm, nest_mul_simple_v1) <int64> x);
ssa! ((vm, nest_mul_simple_v1) <int64> y);
ssa! ((vm, nest_mul_simple_v1) <int64> z);
// %a = MUL %x %y
ssa! ((vm, nest_mul_simple_v1) <int64> a);
inst! ((vm, nest_mul_simple_v1) blk_entry_mul1:
a = BINOP (BinOp::Mul) x y
);
// %b = MUL %a %z
ssa! ((vm, nest_mul_simple_v1) <int64> b);
inst! ((vm, nest_mul_simple_v1) blk_entry_mul2:
b = BINOP (BinOp::Mul) a z
);
// RET b
inst! ((vm, nest_mul_simple_v1) blk_entry_ret:
RET (b)
);
define_block!((vm, nest_mul_simple_v1) blk_entry(x, y, z) {
blk_entry_mul1,
blk_entry_mul2,
blk_entry_ret
});
define_func_ver!((vm) nest_mul_simple_v1(entry: blk_entry) {
blk_entry
});
vm
}
#[test]
fn test_nest_mul_times_10() {
VM::start_logging_trace();
let lib = linkutils::aot::compile_fnc("nest_mul_times_10", &nest_mul_times_10);
unsafe {
let nest_mul: libloading::Symbol<unsafe extern "C" fn(u64, u64) -> u64> =
lib.get(b"nest_mul_times_10").unwrap();
let res = nest_mul(2, 3);
println!("mul(2, 3) x 10 = {}", res);
assert_eq!(res, 60);
}
}
fn nest_mul_times_10() -> VM {
let vm = VM::new();
typedef! ((vm) int64 = mu_int(64));
constdef! ((vm) <int64> int64_10 = Constant::Int(10));
funcsig! ((vm) sig = (int64, int64) -> (int64));
funcdecl! ((vm) <sig> nest_mul_times_10);
funcdef! ((vm) <sig> nest_mul_times_10 VERSION nest_mul_times_10_v1);
// %entry(%x, %y)
block! ((vm, nest_mul_times_10_v1) blk_entry);
ssa! ((vm, nest_mul_times_10_v1) <int64> x);
ssa! ((vm, nest_mul_times_10_v1) <int64> y);
consta! ((vm, nest_mul_times_10_v1) int64_10_local = int64_10);
// %a = MUL %x %y
ssa! ((vm, nest_mul_times_10_v1) <int64> a);
inst! ((vm, nest_mul_times_10_v1) blk_entry_mul1:
a = BINOP (BinOp::Mul) x y
);
// %b = MUL 10 %a
ssa! ((vm, nest_mul_times_10_v1) <int64> b);
inst! ((vm, nest_mul_times_10_v1) blk_entry_mul2:
b = BINOP (BinOp::Mul) int64_10_local a
);
// RET b
inst! ((vm, nest_mul_times_10_v1) blk_entry_ret:
RET (b)
);
define_block!((vm, nest_mul_times_10_v1) blk_entry(x, y) {
blk_entry_mul1,
blk_entry_mul2,
blk_entry_ret
});
define_func_ver!((vm) nest_mul_times_10_v1(entry: blk_entry) {
blk_entry
});
vm
}
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