Commit e28cb012 authored by qinsoon's avatar qinsoon

call with int128 on x86_64

parent bc6b8e78
......@@ -3082,6 +3082,19 @@ impl <'a> InstructionSelection {
// get return value by stack
unimplemented!()
}
} else if RegGroup::get_from_value(&ret_val) == RegGroup::GPREX && ret_val.is_reg() {
if gpr_ret_count + 1 < x86_64::RETURN_GPRs.len() {
let ret_gpr1 = x86_64::RETURN_GPRs[gpr_ret_count].clone();
let ret_gpr2 = x86_64::RETURN_GPRs[gpr_ret_count + 1].clone();
let (ret_val_l, ret_val_h) = self.split_int128(&ret_val, f_context, vm);
self.backend.emit_mov_r_r(&ret_val_l, &ret_gpr1);
self.backend.emit_mov_r_r(&ret_val_h, &ret_gpr2);
} else {
// get return value by stack
unimplemented!()
}
} else if RegGroup::get_from_value(&ret_val) == RegGroup::FPR && ret_val.is_reg() {
// floating point register
if fpr_ret_count < x86_64::RETURN_FPRs.len() {
......@@ -3262,6 +3275,9 @@ impl <'a> InstructionSelection {
} else if self.match_ireg(arg) {
let arg = self.emit_ireg(arg, f_content, f_context, vm);
arg_values.push(arg);
} else if self.match_ireg_ex(arg) {
let arg = self.emit_ireg_ex_as_one(arg, f_content, f_context, vm);
arg_values.push(arg);
} else if self.match_fpreg(arg) {
let arg = self.emit_fpreg(arg, f_content, f_context, vm);
arg_values.push(arg);
......@@ -3889,7 +3905,12 @@ impl <'a> InstructionSelection {
self.backend.emit_mov_r64_imm64(&tmp, val as i64);
}
},
&Constant::IntEx(ref vals) => { unimplemented!() },
&Constant::IntEx(ref vals) => {
let (tmp_l, tmp_h) = self.split_int128(&tmp, f_context, vm);
self.backend.emit_mov_r64_imm64(&tmp_l, vals[0] as i64);
self.backend.emit_mov_r64_imm64(&tmp_h, vals[1] as i64);
},
&Constant::FuncRef(func_id) => {
if cfg!(target_os = "macos") {
let mem = self.get_mem_for_funcref(func_id, vm);
......@@ -3952,6 +3973,10 @@ impl <'a> InstructionSelection {
}
}
fn emit_ireg_ex_as_one(&mut self, op: &TreeNode, f_content: &FunctionContent, f_context: &mut FunctionContext, vm: &VM) -> P<Value> {
self.emit_ireg(op, f_content, f_context, vm)
}
fn emit_fpreg(&mut self, op: &TreeNode, f_content: &FunctionContent, f_context: &mut FunctionContext, vm: &VM) -> P<Value> {
match op.v {
TreeNode_::Instruction(_) => {
......
......@@ -1291,4 +1291,96 @@ fn store_funcref() -> VM {
});
vm
}
use test_compiler::test_int128::add_u128;
#[test]
fn test_call_int128_arg() {
VM::start_logging_trace();
let vm = Arc::new(add_u128());
call_add_u128(&vm);
let func_add = vm.id_of("add_u128");
let func_call = vm.id_of("call_add_u128");
let compiler = Compiler::new(CompilerPolicy::default(), &vm);
{
let funcs = vm.funcs().read().unwrap();
let func_vers = vm.func_vers().read().unwrap();
{
let func = funcs.get(&func_add).unwrap().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
{
let func = funcs.get(&func_call).unwrap().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
}
vm.make_primordial_thread(func_call, true, vec![]);
backend::emit_context(&vm);
let executable = aot::link_primordial(vec![Mu("add_u128"), Mu("call_add_u128")], "test_call_int128_arg", &vm);
let output = aot::execute_nocheck(executable);
// exit with (84)
assert!(output.status.code().is_some());
assert_eq!(output.status.code().unwrap(), 84);
}
fn call_add_u128(vm: &VM) {
let add_u128_sig = vm.get_func_sig(vm.id_of("sig"));
let add_u128_id = vm.id_of("add_u128");
typedef! ((vm) int64 = mu_int(64));
typedef! ((vm) int128 = mu_int(128));
constdef! ((vm) <int128> int128_42 = Constant::IntEx(vec![42, 0]));
typedef! ((vm) funcref_add_u128 = mu_funcref(add_u128_sig));
constdef! ((vm) <funcref_add_u128> const_funcref_add_u128 = Constant::FuncRef(add_u128_id));
funcsig! ((vm) call_add_u128_sig = () -> ());
funcdecl! ((vm) <call_add_u128_sig> call_add_u128);
funcdef! ((vm) <call_add_u128_sig> call_add_u128 VERSION call_add_u128_v1);
// blk_entry
block! ((vm, call_add_u128_v1) blk_entry);
// EXPRCALL add_u128 (42, 42)
ssa! ((vm, call_add_u128_v1) <int128> res);
consta! ((vm, call_add_u128_v1) int128_42_local = int128_42);
consta! ((vm, call_add_u128_v1) const_funcref_add_u128_local = const_funcref_add_u128);
inst! ((vm, call_add_u128_v1) blk_entry_call:
res = EXPRCALL (CallConvention::Mu, is_abort: false) const_funcref_add_u128_local (int128_42_local, int128_42_local)
);
ssa! ((vm, call_add_u128_v1) <int64> trunc_res);
inst! ((vm, call_add_u128_v1) blk_entry_trunc:
trunc_res = CONVOP (ConvOp::TRUNC) <int128 int64> res
);
let blk_entry_exit = gen_ccall_exit(trunc_res.clone(), &mut call_add_u128_v1, &vm);
inst! ((vm, call_add_u128_v1) blk_entry_ret:
RET
);
define_block!((vm, call_add_u128_v1) blk_entry() {
blk_entry_call,
blk_entry_trunc,
blk_entry_exit,
blk_entry_ret
});
define_func_ver!((vm) call_add_u128_v1 (entry: blk_entry) {
blk_entry
});
}
\ No newline at end of file
......@@ -29,8 +29,8 @@ fn test_add_u128() {
}
}
fn add_u128() -> VM {
let vm = VM::new();
pub fn add_u128() -> VM {
let vm = VM::new_with_opts("init_mu --disable-inline");
typedef! ((vm) u128 = mu_int(128));
......
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